{"record":{"id":"a05ebe745655e5fa","repo":"musistudio/claude-code-router","slug":"refusing-to-archive-unknown-legacy-json-config-fil","errorCode":null,"errorMessage":"Refusing to archive unknown legacy JSON config file: ${unsupportedFiles.join(\", \")}","messagePattern":"Refusing to archive unknown legacy JSON config file: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/config/config-repository.ts","lineNumber":131,"sourceCode":"\n  async replaceConfigSnapshot(value: unknown, apiKeys: ApiKeyConfig[]): Promise<ApiKeyConfig[]> {\n    const normalized = uniqueApiKeyConfigs(apiKeys);\n    const database = await this.getDatabase();\n    runTransaction(database, () => {\n      replaceAppConfigRow(database, appConfigKey, value);\n      replaceApiKeyRows(database, normalized);\n    });\n    secureDatabaseFilePermissions(this.dbFile);\n    return normalized;\n  }\n\n  async archiveLegacyJsonConfigFiles(files: string[]): Promise<void> {\n    const requestedFiles = uniquePaths(files);\n    const unsupportedFiles = requestedFiles.filter(\n      (file) => !legacyJsonConfigFiles.some((candidate) => samePath(candidate, file))\n    );\n    if (unsupportedFiles.length > 0) {\n      throw new Error(`Refusing to archive unknown legacy JSON config file: ${unsupportedFiles.join(\", \")}`);\n    }\n    if (requestedFiles.length === 0) {\n      return;\n    }\n    const database = await this.getDatabase();\n    archiveAndRemoveFiles(database, requestedFiles, \"legacy-json-config\", this.removeFile);\n  }\n\n  private async getDatabase(): Promise<SqlDatabase> {\n    if (this.database) {\n      return this.database;\n    }\n    this.initPromise ??= this.open();\n    return this.initPromise;\n  }\n\n  private async open(): Promise<SqlDatabase> {\n    const dbDir = dirname(this.dbFile);","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/config/config-repository.ts#L113-L149","documentation":"archiveLegacyJsonConfigFiles only allows archiving files on its known legacyJsonConfigFiles list; anything else is refused to prevent accidentally archiving unknown/critical config.","triggerScenarios":"Passing a file path that doesn't samePath-match any entry in legacyJsonConfigFiles.","commonSituations":"Caller constructs the file list from user input or a newer config schema; case/separator differences on Windows defeating samePath; renamed legacy files.","solutions":["Only pass paths that appear in legacyJsonConfigFiles.","If a new legacy file should be archivable, add it to the legacyJsonConfigFiles allowlist in config-repository.ts.","Normalize path separators/case before calling."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const allowed = legacyJsonConfigFiles;\nconst safe = files.filter(f => allowed.some(a => samePath(a, f)));\nif (safe.length !== files.length) rejectUnknown(files);","typeGuard":"function isLegacyJsonConfigFile(f: string): boolean {\n  return legacyJsonConfigFiles.some(c => samePath(c, f));\n}","tryCatchPattern":null,"preventionTips":["Never feed user-supplied paths straight into archive calls.","Keep the allowlist in sync when legacy files change."],"tags":["config","archive","allowlist"],"backgroundTag":"path-not-allowed","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}