The error comes from createNewDownload(), not from the scanning logic. The scan finds the file correctly. The failure happens inside DownloadModel->save(), which calls ->getTag() on something that is null. Likely cause In this standalone script you build the application from the container, but you never initialise its language object: php $app = $container->get(\Joomla\CMS\Application\AdministratorApplication::class); Factory::getLanguage() works because it uses the container service, but $app->getLanguage() stays null on an uninitialised app. Joomla's save path (the model, tags and associations helpers) calls Factory::getApplication()->getLanguage()->getTag(), which fails with exactly your message. Folder and category detection never touch that code, so only new downloads break. Fix Right after the $app setup, attach the language to the app: php $app = $container->get(\Joomla\CMS\Application\AdministratorApplication::class); $app->createExtensionNamespaceMap(); \Joomla\CMS\Factory::$application = $app; // Give the app a language object (it is null otherwise) $app->setLanguage(\Joomla\CMS\Factory::getLanguage()); If your Joomla 5 version complains that setLanguage doesn't exist, use $app->loadLanguage(\Joomla\CMS\Factory::getLanguage()); instead. Confirming where it fails I can't see the exact line from here. Change the catch in createNewDownload() so it reports where the error occurred: php } catch (Throwable $e) { return ['success' => false, 'error' => $e->getMessage() . ' @ ' . basename($e->getFile()) . ':' . $e->getLine()]; } If the reported file is not a language or tag-related class, send me that file and line. The same null-object problem could also apply to another service, such as $app->getIdentity(). Other bugs I noticed Untranslated error key: the parenthesis is in the wrong place in both error log lines. This is why you see COM_JDOWNLOADS_ERROR_RESULT_MSG: ✗ ... instead of a translated message: php // wrong Text::_('COM_JDOWNLOADS_ERROR_RESULT_MSG' . ': ✗ ' . $folder . ': ' . $result['error']); // right Text::_('COM_JDOWNLOADS_ERROR_RESULT_MSG') . ': ✗ ' . $folder . ': ' . $result['error']; Fix it in processFolderChunk() and processFileChunk(). Misleading summary: "No new Files found." is printed because new_downloads is only incremented on success. When creation fails, the summary hides the failure. Consider counting failures separately. Header doesn't match the run: your log says "Test Run Results", but createNewDownload() only runs when $testrun is false. Check which test value your frontend actually sends, since the header and the real behaviour disagree. Duplicate "Checking all published Categories" line: the log shows it twice. Your missing-files phase probably uses COM_JDOWNLOADS_RUN_MONITORING_INFO6, which may contain the same text as INFO4 in your language file. That would be a language-string issue rather than a code issue. After the language fix, run a real scan on that single file and check the log again. Can you please re-generate the complete fixed script! The complete fixed script is attached as scan_worker_fixed.php. I haven't run it against Joomla, so please test it with a real (non-test) run on your one new MP3. What changed Main fix: after the language is loaded, the app now gets it attached (setLanguage(), or loadLanguage() as a fallback). createNewDownload() also repeats this check as a safety net. This is aimed at the getTag() on null error, though that cause is my best guess, as I couldn't see the exact failing line. Error messages: the misplaced parenthesis in Text::_() is fixed in both the folder and file loops, so you now get the translated message instead of the raw COM_JDOWNLOADS_ERROR_RESULT_MSG key. Failures counted: new failed_cats and failed_downloads counters. "No new Files found." no longer appears when a creation failed. Instead you get a line like "✗ 1 files could not be added as downloads (see errors above)". Better error output: exceptions in createNewCategory() and createNewDownload() now include file and line, e.g. ... @ SomeClass.php:123. Cleanup: I restored the comment above handleStart(), which had been mislabelled as "JSON response helper", and fixed the indentation in the file-pic block. If the error persists The log will now show the file and line where it fails. Send me that and I can pinpoint it. Still unchanged The "Test Run Results" header in your log means that run had test=1. In test mode no downloads are created, so make sure the test checkbox is off in the frontend when you try the real run. The duplicate "Checking all published Categories" line is most likely two identical language strings (INFO4 and INFO6), not a code issue.