{"record":{"id":"f2932687e80be0db","repo":"eyaltoledano/claude-task-master","slug":"config-error-f29326","errorCode":"CONFIG_ERROR","errorMessage":"'Failed to load local configuration'","messagePattern":"'Failed to load local configuration'","errorType":"exception","errorClass":"TaskMasterError","httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/config/services/config-loader.service.ts","lineNumber":97,"sourceCode":"\t\t\t},\n\t\t\tversion: DEFAULT_CONFIG_VALUES.VERSION\n\t\t};\n\t}\n\n\t/**\n\t * Load local project configuration\n\t */\n\tasync loadLocalConfig(): Promise<PartialConfiguration | null> {\n\t\ttry {\n\t\t\tconst configData = await fs.readFile(this.localConfigPath, 'utf-8');\n\t\t\treturn JSON.parse(configData);\n\t\t} catch (error: any) {\n\t\t\tif (error.code === 'ENOENT') {\n\t\t\t\t// File doesn't exist, return null\n\t\t\t\tthis.logger.debug('No local config.json found, using defaults');\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tthrow new TaskMasterError(\n\t\t\t\t'Failed to load local configuration',\n\t\t\t\tERROR_CODES.CONFIG_ERROR,\n\t\t\t\t{ configPath: this.localConfigPath },\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Load global user configuration\n\t * @future-implementation Full implementation pending\n\t */\n\tasync loadGlobalConfig(): Promise<PartialConfiguration | null> {\n\t\t// TODO: Implement in future PR\n\t\t// For now, return null to indicate no global config\n\t\treturn null;\n\n\t\t// Future implementation:","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/config/services/config-loader.service.ts#L79-L115","documentation":"ConfigLoaderService.loadLocalConfig reads the local config.json and returns null when the file simply doesn't exist (ENOENT). For any other read/parse failure it wraps the error in a TaskMasterError with code CONFIG_ERROR and the configPath in details. The original error is attached as the cause.","triggerScenarios":"Calling loadLocalConfig (directly or via localConfig/result getters) when config.json exists but cannot be read or parsed — permission denied, invalid JSON, EISDIR, EACCES, or a disk error.","commonSituations":"Hand-edited config.json with a JSON syntax error; file locked by another process on Windows; permission changes after switching users or running under a service account; config.json is actually a directory; partial write from a crashed process.","solutions":["Open the file at details.configPath and fix JSON syntax errors (run it through a JSON validator)","Fix file permissions/ownership so the current process can read it","If irrecoverable, back up and delete the corrupt config.json — loadLocalConfig then returns null and defaults are used","Recreate the file with `tm` init/context commands rather than by hand"],"exampleFix":"// before\nconst cfg = await loader.loadLocalConfig(); // throws CONFIG_ERROR on corrupt JSON\n// after\nlet cfg;\ntry {\n  cfg = await loader.loadLocalConfig();\n} catch (e) {\n  if (e instanceof TaskMasterError && e.code === 'CONFIG_ERROR') {\n    await fs.rename(e.details.configPath, `${e.details.configPath}.bak`); // quarantine\n    cfg = null; // fall back to defaults\n  } else { throw e; }\n}","handlingStrategy":"try-catch","validationCode":"import { stat } from 'fs/promises';\ntry {\n  const s = await stat(configPath);\n  if (!s.isFile()) throw new Error(`${configPath} is not a regular file`);\n  JSON.parse(await readFile(configPath, 'utf-8')); // detect corrupt JSON early\n} catch (err) {\n  if ((err as NodeJS.ErrnoException).code === 'ENOENT') { /* fine: defaults will be used */ }\n  else throw err;\n}","typeGuard":"function isConfigError(e: unknown): e is TaskMasterError {\n  return e instanceof TaskMasterError && e.code === 'CONFIG_ERROR';\n}","tryCatchPattern":"try {\n  cfg = await loader.loadLocalConfig();\n} catch (e) {\n  if (isConfigError(e)) {\n    // e.details.configPath: quarantine/repair file, then fall back to defaults\n    cfg = null;\n  } else { throw e; }\n}","preventionTips":["Don't hand-edit config.json; use tm commands that validate on write","Validate JSON with a linter after any manual edit","Keep only one process/tool owning the config file to avoid partial writes","Back up the file before bulk changes; a null return (missing) is fine, CONFIG_ERROR means it exists but is broken"],"tags":["config","filesystem","json"],"backgroundTag":"config-file-corrupt","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}