{"record":{"id":"ec1b8385deb81dbe","repo":"tobi/qmd","slug":"failed-to-parse-configpath-error","errorCode":null,"errorMessage":"Failed to parse ${configPath}: ${error}","messagePattern":"Failed to parse (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/collections.ts","lineNumber":202,"sourceCode":"  // File-based config (SDK custom path or default)\n  const configPath = configSource.path || getConfigFilePath();\n  if (!existsSync(configPath)) {\n    return { collections: {} };\n  }\n\n  try {\n    const content = readFileSync(configPath, \"utf-8\");\n    const parsed = YAML.parse(content) as CollectionConfig | null | undefined;\n    const config = parsed ?? { collections: {} };\n\n    // Ensure collections object exists\n    if (!config.collections) {\n      config.collections = {};\n    }\n\n    return config;\n  } catch (error) {\n    throw new Error(`Failed to parse ${configPath}: ${error}`);\n  }\n}\n\n/**\n * Save configuration to the configured source.\n * - Inline config: updates the in-memory object (no file I/O)\n * - File-based: writes to YAML file (default ~/.config/qmd/index.yml)\n */\nexport function saveConfig(config: CollectionConfig): void {\n  // SDK inline config mode: update in place, no file I/O\n  if (configSource.type === 'inline') {\n    configSource.config = config;\n    return;\n  }\n\n  const configPath = configSource.path || getConfigFilePath();\n  const configDir = dirname(configPath);\n  if (!existsSync(configDir)) {","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/tobi/qmd/blob/dbfd0b4736aeaf761d1a16ca8e424f071df8feb9/src/collections.ts#L184-L220","documentation":"loadConfig failed while reading the QMD YAML config file. The file exists but its contents could not be parsed as YAML (or the parsed result was unusable), so the raw parser error is wrapped with the offending path. This is thrown from loadConfig, which backs config loading for the CLI and createStore.","triggerScenarios":"Calling createStore({configPath: './qmd.yaml'}) or any qmd CLI command when the YAML config has a syntax error: bad indentation, unclosed quote, tabs, or pasted markdown mixed into the YAML.","commonSituations":"Hand-editing ~/.config/qmd/config.yaml or a project .qmd config and breaking YAML syntax; merging config changes via git producing conflicts left in the file; empty file with invalid BOM or non-UTF8 bytes.","solutions":["Run `qmd doctor` to diagnose config issues","Inspect the file named in the message with a YAML linter and fix indentation/quotes","If unsure, delete the corrupt config and regenerate with `qmd collection add` or `qmd init`","Keep configs out of manual edits; use qmd CLI commands to mutate them"],"exampleFix":"# before (broken)\ncollections:\n  notes:\n  path: ~/notes   # bad indentation\n# after\ncollections:\n  notes:\n    path: ~/notes\n","handlingStrategy":"validation","validationCode":"import { readFileSync } from 'node:fs';\nimport { parse } from 'yaml';\n\nfunction configLooksValid(configPath: string): boolean {\n  try { parse(readFileSync(configPath, 'utf-8')); return true; }\n  catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const store = await createStore({ dbPath, configPath });\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Failed to parse')) {\n    console.error('Config syntax error:', e.message);\n  } else throw e;\n}","preventionTips":["Validate config YAML in CI before deploying","Let qmd CLI commands mutate the config instead of hand editing","Keep the config under version control to diff breakage"],"tags":["yaml","config","parse-error"],"backgroundTag":"yaml-parse-error","analyzedSha":"dbfd0b4736aeaf761d1a16ca8e424f071df8feb9","analyzedAt":"2026-08-28T18:07:46.628Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}