{"record":{"id":"df7bd7b136794543","repo":"tobi/qmd","slug":"provide-either-configpath-or-config-not-both","errorCode":null,"errorMessage":"Provide either configPath or config, not both","messagePattern":"Provide either configPath or config, not both","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/index.ts","lineNumber":357,"sourceCode":" * const store = await createStore({\n *   dbPath: './index.sqlite',\n *   config: {\n *     collections: {\n *       docs: { path: '/path/to/docs', pattern: '**\\/*.md' }\n *     }\n *   }\n * })\n *\n * const results = await store.search({ query: \"authentication flow\" })\n * await store.close()\n * ```\n */\nexport async function createStore(options: StoreOptions): Promise<QMDStore> {\n  if (!options.dbPath) {\n    throw new Error(\"dbPath is required\");\n  }\n  if (options.configPath && options.config) {\n    throw new Error(\"Provide either configPath or config, not both\");\n  }\n\n  // Create the internal store (opens DB, creates tables)\n  const internal = createStoreInternal(options.dbPath);\n  const db = internal.db;\n\n  // Track whether we have a YAML config path for write-through\n  const hasYamlConfig = !!options.configPath;\n\n  // Sync config into SQLite store_collections\n  let config: CollectionConfig | undefined;\n  if (options.configPath) {\n    // YAML mode: inject config source for write-through, sync to DB\n    setConfigSource({ configPath: options.configPath });\n    config = loadConfig();\n    syncConfigToDb(db, config);\n  } else if (options.config) {\n    // Inline config mode: inject config source for mutations, sync to DB","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/tobi/qmd/blob/dbfd0b4736aeaf761d1a16ca8e424f071df8feb9/src/index.ts#L339-L375","documentation":"createStore accepts configuration either from a file (configPath) or an inline object (config), but not both — specifying both makes it ambiguous which one wins, so it rejects the call upfront.","triggerScenarios":"Calling createStore({dbPath, configPath: './qmd.yaml', config: {collections: {...}}}) with both fields set.","commonSituations":"Layered app configs merging defaults (file) with overrides (inline object); copy-pasting examples that each used a different option; passing process.env-based config alongside a checked-in config path.","solutions":["Pick one source: delete configPath if you have an inline config object, or drop config to load from file","Load the file yourself once and merge into a single inline config object"],"exampleFix":"// before\nawait createStore({\n  dbPath: './db.sqlite',\n  configPath: './qmd.yaml',\n  config: myConfig,\n});\n// after\nawait createStore({\n  dbPath: './db.sqlite',\n  config: myConfig,\n});\n","handlingStrategy":"validation","validationCode":"if (options.configPath && options.config) {\n  delete options.configPath; // or merge: load file then deep-merge inline config\n}","typeGuard":"const isExclusiveConfig = (o: StoreOptions): boolean =>\n  !(o.configPath && o.config);","tryCatchPattern":null,"preventionTips":["Pick one config source per project and stick to it","If merging file + overrides is needed, load and merge yourself, pass only `config`","Use TypeScript's discriminated unions or a lint rule against passing both keys"],"tags":["api-misuse","validation","mutually-exclusive"],"backgroundTag":"conflicting-options","analyzedSha":"dbfd0b4736aeaf761d1a16ca8e424f071df8feb9","analyzedAt":"2026-08-28T18:07:46.628Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}