affaan-m/ECC · error · anyhow::Error
legacy scheduler jobs file must be a JSON object or array
Error message
legacy scheduler jobs file must be a JSON object or array: {} What it means
The legacy scheduler import parses the jobs file as JSON and accepts only a top-level object or array; any other JSON top-level value (string, number, boolean, null) triggers this bail with the file path. The importer needs a collection shape to extract job entries.
Solutions
- Check the file's top-level value (`jq 'type' <file>`) and fix the export to produce an object or array of jobs.
- Point the import at the correct legacy jobs JSON file.
- If the export is `null` because there were no jobs, skip the import or replace the file with `[]`.
Example fix
// before (jobs.json) null // after (jobs.json) []
Defensive patterns
Strategy: validation
Validate before calling
// Check the JSON root shape before import
const jobs = JSON.parse(fs.readFileSync(jobsPath, 'utf8'));
if (jobs === null || typeof jobs !== 'object') {
throw new Error(`jobs file root must be object or array: ${jobsPath}`);
} Type guard
function isJobCollection(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v)
? true
: Array.isArray(v);
} Try / catch
match parse_legacy_jobs(&jobs_path) {
Err(e) if e.to_string().contains("must be a JSON object or array") => {
eprintln!("Fix the export or point at the correct jobs file: {}", jobs_path.display());
}
other => other?,
} Prevention
- Run `jq 'type' file.json` to verify the root shape before importing.
- Ensure your export tool writes `[]` (not `null`) when there are no jobs.
- Add a JSON schema for the jobs file and validate exports at creation time.
When it happens
Trigger: Pointing the legacy schedule import at a JSON file whose root is a scalar (e.g. a file containing `{}` is fine, but `"jobs"` or `42` is not); feeding the wrong file (a settings file or scalar export) as the jobs file.
Common situations: An export tool wrote a scalar/null (e.g. when there were no jobs it wrote `null`); the user passed the wrong JSON file to the importer; an older export format with a different root shape.
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
- candidate configuration exceeds 1 MiB
- ! : invalid meta.json, continuing with defaults ( )
- Legacy workspace not found
- Legacy workspace source must be a directory
- agent profile inheritance cycle
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/19578188ee655aae.
Report an issue: GitHub.
Appendix: source
Thrown at ecc2/src/main.rs:5530
let source_path = jobs_path
.strip_prefix(source)
.unwrap_or(&jobs_path)
.display()
.to_string();
let entries: Vec<&serde_json::Value> = match &value {
serde_json::Value::Array(items) => items.iter().collect(),
serde_json::Value::Object(map) => {
if let Some(items) = ["jobs", "schedules", "tasks"]
.iter()
.find_map(|key| map.get(*key).and_then(serde_json::Value::as_array))
{
items.iter().collect()
} else {
vec![&value]
}
}
_ => anyhow::bail!(
"legacy scheduler jobs file must be a JSON object or array: {}",
jobs_path.display()
),
};
Ok(entries
.into_iter()
.enumerate()
.map(|(index, value)| build_legacy_schedule_draft(value, index, &source_path))
.collect())
}
fn load_legacy_remote_dispatch_drafts(source: &Path) -> Result<Vec<LegacyRemoteDispatchDraft>> {
let gateway_dir = source.join("gateway");
if !gateway_dir.is_dir() {
return Ok(Vec::new());
}
View on GitHub (pinned to 8321021c54)