freeCodeCamp/freeCodeCamp · error · Error
No challenge files provided
Error message
No challenge files provided
What it means
Thrown by buildPythonChallenge in the challenge-builder package when it is dispatched without source files. Python challenges are built by piping every entry of challengeFiles through getPythonTransformers(), so the function guards its input first and throws synchronously when challengeFiles is undefined or null rather than producing an empty build. BuildChallengeData types the field as optional (challengeFiles?), so TypeScript does not flag the missing field at the call site.
Source
Thrown at packages/challenge-builder/src/build.ts:321
.join('\n'),
sources: buildSourceMap(finalFiles),
error
};
}
function buildBackendChallenge({ url, challengeType }: BuildChallengeData) {
return {
challengeType,
build: '',
sources: { contents: url }
};
}
async function buildPythonChallenge({
challengeFiles,
challengeType
}: BuildChallengeData): Promise<BuildResult> {
if (!challengeFiles) throw new Error('No challenge files provided');
const pipeLine = composeFunctions(
...(getPythonTransformers() as unknown as ApplyFunctionProps[])
);
const finalFiles = await Promise.all(challengeFiles.map(pipeLine));
const error = finalFiles.find(({ error }) => error)?.error;
const sources = buildSourceMap(finalFiles);
return {
challengeType,
sources,
build: sources?.contents,
error
};
}
View on GitHub (pinned to 4289125977)
Solutions
- Pass the sources in: buildPythonChallenge({ challengeType, challengeFiles }) with a populated ChallengeFile[] (fileKey, path, contents).
- Log the incoming challenge object right before dispatch when challengeFiles is missing, to identify which curriculum record is malformed.
- Check the upstream mapping that builds BuildChallengeData - confirm the key name is challengeFiles and the array survives parsing.
- If missing files is legitimate for some types, branch in the dispatcher before calling buildPythonChallenge instead of relying on the throw.
Example fix
// before
buildPythonChallenge({ challengeType });
// after
buildPythonChallenge({ challengeType, challengeFiles }); Defensive patterns
Strategy: validation
Validate before calling
const files = challenge.challengeFiles;
if (!Array.isArray(files) || files.length === 0) {
throw new Error('Python challenge ' + challenge.id + ' has no challengeFiles');
}
return buildPythonChallenge({
challengeType: challenge.challengeType,
challengeFiles: files
}); Type guard
type BuildablePythonData = BuildChallengeData & {
challengeFiles: NonNullable<BuildChallengeData['challengeFiles']>;
};
const hasPythonFiles = (
data: BuildChallengeData
): data is BuildablePythonData => Array.isArray(data.challengeFiles); Try / catch
try {
const result = await buildChallenge(challenge);
} catch (err) {
if (err instanceof Error && err.message === 'No challenge files provided') {
logger.warn({ id: challenge.id }, 'skipped: challenge has no files');
continue;
}
throw err;
} Prevention
- Make challengeFiles required in the type the Python builder accepts, so the compiler flags every caller missing files.
- Validate challenge definitions with a schema (typebox or zod) that requires challengeFiles for Python challengeTypes at ingestion.
- Include the challenge id when re-throwing so batch builds identify the offending record.
- Unit-test the dispatcher with a files-less challenge to assert it fails fast with a clear message.
When it happens
Trigger: Calling buildChallenge or buildPythonChallenge with an object whose challengeFiles key is absent, null, or undefined - for example buildPythonChallenge({ challengeType: 28 }). In practice: the curriculum or database record for a Python challenge ships no files, a data-loading step drops or renames the field (files vs challengeFiles), or a newly routed Python challengeType reaches this builder although its data shape has no files.
Common situations: Adding a new Python-based challengeType to the dispatcher without confirming its curriculum objects carry files; ingesting challenge JSON whose property is named differently; destructuring or optional-chaining mistakes producing undefined. The sibling buildJsChallenge has the same guard (build.ts:284), so refactors often hit both.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- TypeScript challenge must include only one tsconfig.json fil
- A required file can not have both a src and a link: src = $
- No html, ts(x) or js(x) file found
- Cannot build challenge of type ${challengeType}
- flash.wrong-name
AI-assisted analysis of freeCodeCamp/freeCodeCamp@4289125977 (2026-08-24).
Data as JSON: /api/errors/ad2cf0b7fbab65c1.
Report an issue: GitHub.