slopus/happy · warning
Failed to read settings: ${error.message}
Error message
Failed to read settings: ${error.message} What it means
readSettings wraps the entire load-and-migrate pipeline in a try/catch. If anything throws — unreadable file, malformed JSON, a bug in migration, or an unexpected error in merging — this warning is logged and default settings are returned so the CLI keeps working. It swallows the real error, so the message text is the only diagnostic.
Source
Thrown at packages/happy-cli/src/persistence.ts:118
);
}
// Migrate if needed
const migrated = migrateSettings(raw, schemaVersion);
if (migrated.sandboxConfig !== undefined) {
try {
migrated.sandboxConfig = SandboxConfigSchema.parse(migrated.sandboxConfig);
} catch (error: any) {
logger.warn(`⚠️ Invalid sandbox config - skipping. Error: ${error.message}`);
migrated.sandboxConfig = undefined;
}
}
// Merge with defaults to ensure all required fields exist
return { ...defaultSettings, ...migrated };
} catch (error: any) {
logger.warn(`Failed to read settings: ${error.message}`);
// Return defaults on any error
return { ...defaultSettings }
}
}
export async function writeSettings(settings: Settings): Promise<void> {
if (!existsSync(configuration.happyHomeDir)) {
await mkdir(configuration.happyHomeDir, { recursive: true })
}
// Ensure schema version is set before writing
const settingsWithVersion = {
...settings,
schemaVersion: settings.schemaVersion ?? SUPPORTED_SCHEMA_VERSION
};
await writeFile(configuration.settingsFile, JSON.stringify(settingsWithVersion, null, 2))
}View on GitHub (pinned to b824cd0a46)
Solutions
- Check the error.message in the warning to see whether it's ENOENT, EACCES, or a JSON parse error.
- Fix file permissions (chmod/chown) or restore the settings file; delete it to reset to defaults.
- Validate the JSON (e.g. jq . ~/.happy/settings.json) and fix syntax errors.
- Back up the file, delete it, and reconfigure happy from scratch.
Example fix
// before (corrupt JSON)
{ "defaultMode": "sandbox", }
// after
{ "defaultMode": "sandbox" } Defensive patterns
Strategy: fallback
Validate before calling
const p = require('os').homedir() + '/.happy/settings.json';
try {
JSON.parse(require('fs').readFileSync(p, 'utf8'));
} catch (e) {
console.error(`Settings file ${p} is unreadable/invalid: ${e.message} — remove or fix it before running happy.`);
} Try / catch
// happy already falls back to defaults internally; on your side:
try {
const settings = await readSettings();
} catch (e) {
// note: readSettings itself swallows errors, so guard the file first
const defaults = { ...defaultSettings };
} Prevention
- Validate settings JSON with `jq` or an editor with JSON linting before saving.
- Ensure atomic writes (happy does tmp+rename); avoid killing the CLI mid-write.
- Check file permissions on ~/.happy after OS/user changes.
- Back up settings.json before upgrading happy.
When it happens
Trigger: readSettings called (via settings() or current()) when the settings file is missing/unreadable, contains invalid JSON, or migrateSettings throws on an incompatible schemaVersion.
Common situations: Permissions problem on ~/.happy, partial/corrupt settings.json from a crashed write, JSON edited with trailing commas or comments, or an older settings file whose schemaVersion breaks migration.
Related errors
- No machine ID found in settings
- No machine ID found in settings
- No machine ID found in settings
- Failed to acquire settings lock after ${MAX_LOCK_ATTEMPTS *
- ⚠️ Settings schema v${schemaVersion} > supported v${SUPPORTE
AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31).
Data as JSON: /api/errors/4ca2fe04036b67e2.
Report an issue: GitHub.