{"record":{"id":"66236ca6b943f722","repo":"abhigyanpatwari/GitNexus","slug":"expected-a-yaml-object","errorCode":null,"errorMessage":"expected a YAML object","messagePattern":"expected a YAML object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/auto-sync/config.ts","lineNumber":114,"sourceCode":"      message: `[auto-sync] Unable to read config file: ${configPath}. Auto sync is skipped.`,\n    };\n  }\n\n  try {\n    return { ok: true, config: parseAutoSyncConfig(content, configPath) };\n  } catch (err: unknown) {\n    return {\n      ok: false,\n      reason: 'invalid',\n      message: `[auto-sync] Invalid watch_config.yml: ${(err as Error).message}. Auto sync is skipped.`,\n    };\n  }\n}\n\nexport function parseAutoSyncConfig(content: string, configPath: string): AutoSyncConfig {\n  const raw = yaml.load(content, { schema: yaml.JSON_SCHEMA }) as Record<string, unknown>;\n  if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n    throw new Error('expected a YAML object');\n  }\n\n  const errors: string[] = [];\n  const interval = Number(raw.sync_interval_minutes);\n  if (!Number.isInteger(interval) || interval <= 0) {\n    errors.push('sync_interval_minutes must be a positive integer');\n  } else if (interval < MIN_SYNC_INTERVAL_MINUTES) {\n    errors.push(`sync_interval_minutes must be at least ${MIN_SYNC_INTERVAL_MINUTES}`);\n  } else if (interval > MAX_SYNC_INTERVAL_MINUTES) {\n    errors.push(`sync_interval_minutes must not exceed ${MAX_SYNC_INTERVAL_MINUTES}`);\n  }\n\n  // YAML booleans survive JSON_SCHEMA (`true`/`false`). `Number(true) === 1`\n  // would otherwise pass the integer check and silently mean concurrency 1.\n  let maxConcurrency = DEFAULT_MAX_CONCURRENCY;\n  if (raw.max_concurrency !== undefined) {\n    if (typeof raw.max_concurrency !== 'number' || !Number.isInteger(raw.max_concurrency)) {\n      errors.push('max_concurrency must be a positive integer');","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/core/auto-sync/config.ts#L96-L132","documentation":"parseAutoSyncConfig() loads the auto-sync YAML file with the JSON schema and requires the top-level document to be a plain object (mapping). It throws 'expected a YAML object' when the parsed document is null, a scalar, or an array — the auto-sync config format only supports a mapping at the root.","triggerScenarios":"A .gitnexus auto-sync config file whose content parses to a list (e.g. starts with '-'), an empty file (yaml.load returns null), or a bare scalar like just a number or quoted string.","commonSituations":"Accidentally pasting a YAML list of repos instead of a mapping, an empty config file created by touch, or YAML that's just a comment so it parses to null.","solutions":["Make the top level a mapping, e.g. sync_interval_minutes: 30 at the root.","Remove surrounding list syntax ('- ' items) or wrap entries under a top-level key.","If the file is empty, populate it with the required keys (sync_interval_minutes at minimum).","Validate the YAML parses to an object: node -e \"console.log(require('js-yaml').load(require('fs').readFileSync(path,'utf8')))\"."],"exampleFix":"// before\n- repo: git@github.com:org/repo.git\n// after\nsync_interval_minutes: 30\nremotes:\n  - git@github.com:org/repo.git","handlingStrategy":"validation","validationCode":"const yaml = require('js-yaml');\nconst doc = yaml.load(fs.readFileSync(cfgPath, 'utf8'), { schema: yaml.JSON_SCHEMA });\nif (!doc || typeof doc !== 'object' || Array.isArray(doc)) throw new Error('auto-sync config must be a YAML mapping');","typeGuard":"const isRecord = (v: unknown): v is Record<string, unknown> =>\n  typeof v === 'object' && v !== null && !Array.isArray(v);","tryCatchPattern":null,"preventionTips":["Ensure the config's top level is a key: value mapping, not a list","Don't leave the config file empty — an empty YAML parses to null","Lint the YAML with a parser before saving"],"tags":["yaml","configuration","auto-sync","validation"],"backgroundTag":"config-type-mismatch","analyzedSha":"0d1aed942f0e8b5d3bac27519fff441aceea722d","analyzedAt":"2026-09-08T00:40:44.970Z","contentChangedAt":"2026-09-08T00:40:44.970Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}