Hmbown/CodeWhale · error · Error
source invalid:\n
Error message
source invalid:\n - ${errors.join("\n - ")} What it means
buildPayload validates the facts source file with validateSource before constructing the signed payload. If any validation errors are found, it throws one aggregated error listing every offending field, so publishers fix the whole source in one pass instead of one error per run.
Solutions
- Read the '- ' lines in the thrown message; each names a specific validation failure in the source
- Fix every listed field in the source file (types, required keys, allowed values)
- Regenerate the source with the official build tooling instead of hand-editing
Example fix
// before
const payload = buildPayload({ version: '1.2.3' }, opts); // missing required fields
// after
const payload = buildPayload({ version: '1.2.3', applies_to: '*', release: null, announcements: [] }, opts); Defensive patterns
Strategy: try-catch
Validate before calling
const errors = validateSource(source);
if (errors.length) { console.error(errors.join('\n')); process.exit(2); } Try / catch
try { buildPayload(source, opts); } catch (e) { if (e.message.startsWith('source invalid:')) { for (const line of e.message.split('\n - ').slice(1)) console.error('fix:', line); process.exitCode = 2; } else throw e; } Prevention
- Run validateSource as a pre-publish lint step
- Generate the source with the official tooling, not hand edits
- Pin the source schema version and validate on upgrade
When it happens
Trigger: Calling buildPayload with a source missing required fields, having wrong-typed values (e.g. announcements not an array, bad release value), or otherwise failing validateSource's checks.
Common situations: Hand-editing the facts source JSON and dropping a required key, a schema drift after adding new fields, or generating the source programmatically with a bug.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- bad channel slug
- Codewhale terminal receipt contained a non-scalar field
- Duplicate .
- Duplicate policy identity.
- Facts must be scalar metadata, not content objects.
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/494ac136c9fe49c7.
Report an issue: GitHub.
Appendix: source
Thrown at web/scripts/facts-publish.mjs:275
seen.add(a.id);
if (a.level !== undefined && !LEVELS.has(a.level)) errors.push(`${where}.level must be info|warn`);
if (typeof a.text !== "string" || !a.text.trim() || a.text.length > 200) errors.push(`${where}.text required (<= 200 chars)`);
optString(errors, where, a, "url", 300);
if (a.surfaces !== undefined && !(Array.isArray(a.surfaces) && a.surfaces.every((s) => SURFACES.has(s)))) errors.push(`${where}.surfaces invalid`);
optVersionReq(errors, where, a);
optString(errors, where, a, "starts_at", 40);
optString(errors, where, a, "expires_at", 40);
});
}
const allowed = new Set(["$schema", "_meta", "schema_version", "channel", "facts_version", "published_at", "not_after", "applies_to", "models", "provider_defaults", "release", "announcements"]);
for (const k of Object.keys(source)) if (!allowed.has(k)) errors.push(`unknown top-level field ${k}`);
return errors;
}
/** Build the signed payload object (no signing) from a source file. */
export function buildPayload(source, { channel, factsVersion, publishedAt }) {
const errors = validateSource(source);
if (errors.length) throw new Error(`source invalid:\n - ${errors.join("\n - ")}`);
const payload = {
schema_version: SCHEMA_VERSION,
channel,
facts_version: factsVersion,
published_at: publishedAt,
applies_to: typeof source.applies_to === "string" ? source.applies_to.trim() : "*",
models: source.models ?? [],
provider_defaults: source.provider_defaults ?? {},
release: source.release ?? null,
announcements: source.announcements ?? [],
};
if (source.not_after) payload.not_after = source.not_after;
const payloadErrors = validateSource(payload);
if (payloadErrors.length || utcTime(publishedAt) === null || !Number.isSafeInteger(factsVersion) || factsVersion <= 0 || !CHANNEL_RE.test(channel)) {
throw new Error("invalid signed payload metadata");
}
return payload;
}View on GitHub (pinned to 433685b202)