decolua/9router · warning
[DATA_DIR] '${configured}' not writable → fallback ~/.${APP_
Error message
[DATA_DIR] '${configured}' not writable → fallback ~/.${APP_NAME} What it means
getDataDir() honors a user-configured DATA_DIR env var; if creating that directory fails with EACCES or EPERM, it warns and falls back to the default per-user directory (~/.9router, or %APPDATA%\9router on Windows). All MITM/state files then live in the fallback location instead of the configured one. Other mkdir errors (e.g. ENOTDIR, invalid path) are re-thrown.
Source
Thrown at src/mitm/paths.js:22
const APP_NAME = "9router";
function defaultDir() {
if (process.platform === "win32") {
return path.join(process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), APP_NAME);
}
return path.join(os.homedir(), `.${APP_NAME}`);
}
function getDataDir() {
const configured = process.env.DATA_DIR;
if (!configured) return defaultDir();
try {
fs.mkdirSync(configured, { recursive: true });
return configured;
} catch (e) {
if (e?.code === "EACCES" || e?.code === "EPERM") {
console.warn(`[DATA_DIR] '${configured}' not writable → fallback ~/.${APP_NAME}`);
return defaultDir();
}
throw e;
}
}
const DATA_DIR = getDataDir();
const MITM_DIR = path.join(DATA_DIR, "mitm");
module.exports = { DATA_DIR, MITM_DIR };
View on GitHub (pinned to 90b52e06ff)
Solutions
- Fix permissions on the configured DATA_DIR: chown/chmod it so the running user can write (sudo chown -R $USER <dir>).
- Pick a writable DATA_DIR (e.g. /var/lib/9router with proper ownership, or a user-owned path) and restart.
- If the fallback is acceptable, unset DATA_DIR or copy old data from the configured dir into ~/.9router to keep history.
- If the error persists as a non-EACCES crash, fix the invalid path value in DATA_DIR (trailing garbage, wrong drive).
Example fix
// before DATA_DIR=/var/lib/9router # owned by root → EACCES fallback // after sudo mkdir -p /var/lib/9router && sudo chown $USER /var/lib/9router export DATA_DIR=/var/lib/9router
Defensive patterns
Strategy: validation
Validate before calling
// validate DATA_DIR before starting the app
import fs from "fs";
const dir = process.env.DATA_DIR;
if (dir) {
try {
fs.mkdirSync(dir, { recursive: true });
fs.accessSync(dir, fs.constants.W_OK);
console.log("DATA_DIR OK:", dir);
} catch (e) {
console.error("DATA_DIR not writable:", e.code); // expect fallback to ~/.9router
}
} Prevention
- chown/chmod the configured DATA_DIR to the user running the app.
- Never point DATA_DIR at protected system paths (Program Files, /etc, /usr).
- In Docker, mount the data volume read-write, not read-only.
- After seeing this warning, remember data went to ~/.9router — migrate old files there if needed.
When it happens
Trigger: DATA_DIR env is set but mkdirSync(configured, {recursive:true}) fails with EACCES/EPERM: path owned by another user, read-only mount, sandbox/container restrictions, or a protected system path.
Common situations: Docker volume mounted read-only; running the app as non-root with DATA_DIR=/etc or /var/9router owned by root; Windows Program Files as target; systemd service with a hardened ProtectHome/ReadOnlyPaths; macOS sandbox denying a custom path.
Related errors
- [DATA_DIR] '${configured}' not writable → fallback ~/.${APP_
- "No JSON found in decoded code"
- "No JSON found in decoded code"
- Access denied
- Failed to get Copilot token: ${error}
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/c49a6705fec1ae41.
Report an issue: GitHub.