coleam00/Archon · error
Failed to read MCP config file: ${mcpPath} - ${e.message}
Error message
Failed to read MCP config file: ${mcpPath} - ${e.message} What it means
When reading the MCP config file fails for any reason other than a missing file (EACCES permission denied, EISDIR when the path is a directory, ELOOP on symlink cycles), loadMcpConfig wraps the OS error message into a single error prefixed with the requested path, preserving the underlying cause text for diagnosis.
Source
Thrown at packages/providers/src/mcp/config.ts:142
/**
* Load MCP server config from a JSON file and expand environment variables.
*/
export async function loadMcpConfig(
mcpPath: string,
cwd: string,
envSource: EnvSource = process.env
): Promise<LoadedMcpConfig> {
const fullPath = isAbsolute(mcpPath) ? mcpPath : resolve(cwd, mcpPath);
let raw: string;
try {
raw = await readFile(fullPath, 'utf-8');
} catch (err) {
const e = err as NodeJS.ErrnoException;
if (e.code === 'ENOENT') {
throw new Error(`MCP config file not found: ${mcpPath} (resolved to ${fullPath})`);
}
throw new Error(`Failed to read MCP config file: ${mcpPath} - ${e.message}`);
}
let parsed: Record<string, unknown>;
try {
parsed = JSON.parse(raw) as Record<string, unknown>;
} catch (parseErr) {
const detail = (parseErr as SyntaxError).message;
throw new Error(`MCP config file is not valid JSON: ${mcpPath} - ${detail}`);
}
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
throw new Error(`MCP config must be a JSON object (Record<string, ServerConfig>): ${mcpPath}`);
}
const normalized = normalizeMcpConfig(parsed, mcpPath);
const { expanded, missingVars } = expandEnvVars(normalized, envSource);
const serverNames = Object.keys(expanded);
return { servers: expanded, serverNames, missingVars };View on GitHub (pinned to 0773b97458)
Solutions
- Read the OS message after the dash and fix the cause (chmod/chown the file, or correct the path if it is a directory).
- Run: ls -la <resolved-path> to check permissions and type.
- In containers, ensure the file is mounted readable by the process user.
Example fix
// before -rw------- 1 root root .mcp.json # process runs as non-root: EACCES // after $ chmod 644 .mcp.json # or chown to the running user
Defensive patterns
Strategy: try-catch
Validate before calling
import { statSync, accessSync, constants } from 'fs';
const st = statSync(fullPath); // throws EACCES/EISDIR before loadMcpConfig if unreadable
accessSync(fullPath, constants.R_OK); Try / catch
try {
const cfg = await loadMcpConfig(p, cwd);
} catch (err) {
if (err.message.startsWith('Failed to read MCP config file')) {
console.error(`Unreadable MCP config: ${err.message}. Check permissions/ownership.`);
} else throw err;
} Prevention
- Deploy configs with 644 and correct ownership for the process user.
- Verify the path is a file, not a directory (statSync().isFile()).
- In containers, mount config files readable by the runtime user.
When it happens
Trigger: loadMcpConfig where the path points to a directory, the file is chmod 000 or owned by another user, an NFS/symlink issue occurs, or the disk errors during read.
Common situations: Clone/config checked out without read permissions; running the process as a different user (container user mismatch); pointing at ~/.mcp.json while it is actually a directory; overly restrictive umask in CI.
Related errors
- MCP config file not found: ${mcpPath} (resolved to ${fullPat
- EACCES
- Error loading workflows: ${err.message} Hint: Check permissi
- Detached run control directory is owned by another user: ${d
- Detached run control directory must have mode 0700: ${direct
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/18fc77aebb22b771.
Report an issue: GitHub.