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

  1. Check the error.message in the warning to see whether it's ENOENT, EACCES, or a JSON parse error.
  2. Fix file permissions (chmod/chown) or restore the settings file; delete it to reset to defaults.
  3. Validate the JSON (e.g. jq . ~/.happy/settings.json) and fix syntax errors.
  4. 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

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


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/4ca2fe04036b67e2. Report an issue: GitHub.