garrytan/gstack · error · Error
State not found: ${statePath}
Error message
State not found: ${statePath} What it means
On `state load`, the command checks `fs.existsSync(statePath)` (line 954) and throws if the file is absent. The path is built as `<stateDir>/browse-states/<name>.json`, so the error names the resolved absolute path to make it obvious what was looked for.
Source
Thrown at browse/src/meta-commands.ts:954
const stateDir = path.join(config.stateDir, 'browse-states');
mkdirSecure(stateDir);
const statePath = path.join(stateDir, `${name}.json`);
if (action === 'save') {
const state = await bm.saveState();
// V1: cookies + URLs only (not localStorage — breaks on load-before-navigate)
const saveData = {
version: 1,
savedAt: new Date().toISOString(),
cookies: state.cookies,
pages: state.pages.map(p => ({ url: p.url, isActive: p.isActive })),
};
writeSecureFile(statePath, JSON.stringify(saveData, null, 2));
return `State saved: ${statePath} (${state.cookies.length} cookies, ${state.pages.length} pages)\n⚠️ Cookies stored in plaintext. Delete when no longer needed.`;
}
if (action === 'load') {
if (!fs.existsSync(statePath)) throw new Error(`State not found: ${statePath}`);
const data = JSON.parse(fs.readFileSync(statePath, 'utf-8'));
if (!Array.isArray(data.cookies) || !Array.isArray(data.pages)) {
throw new Error('Invalid state file: expected cookies and pages arrays');
}
// Validate and filter cookies — reject malformed or internal-network cookies
const validatedCookies = data.cookies.filter((c: any) => {
if (typeof c !== 'object' || !c) return false;
if (typeof c.name !== 'string' || typeof c.value !== 'string') return false;
if (typeof c.domain !== 'string' || !c.domain) return false;
const d = c.domain.startsWith('.') ? c.domain.slice(1) : c.domain;
if (d === 'localhost' || d.endsWith('.internal') || d === '169.254.169.254') return false;
return true;
});
if (validatedCookies.length < data.cookies.length) {
console.warn(`[browse] Filtered ${data.cookies.length - validatedCookies.length} invalid cookies from state file`);
}
// Warn on state files older than 7 days
if (data.savedAt) {View on GitHub (pinned to 94993f7401)
Solutions
- Run `browse state save <name>` first to create the file.
- Verify the name spelling matches the save call (case-sensitive).
- Check `resolveConfig().stateDir` to confirm the browse-states directory is where you expect.
- List `<stateDir>/browse-states/*.json` to see which saved states actually exist.
Example fix
// before browse state load nope // after browse state save nope && browse state load nope
Defensive patterns
Strategy: try-catch
Validate before calling
const statePath = path.join(config.stateDir, 'browse-states', `${name}.json`);
if (!fs.existsSync(statePath)) {
throw new Error(`No saved state '${name}'. Run: state save ${name}`);
} Try / catch
try { await browse.state('load', name); }
catch (err) {
if (/State not found/.test(err.message)) {
await browse.state('save', name); // create then retry
return browse.state('load', name);
}
throw err;
} Prevention
- Check existence before loading, or save-then-load in a single flow.
- Confirm `stateDir` is stable across sessions (don't rely on a temp dir).
When it happens
Trigger: `browse state load <name>` when no prior `state save <name>` wrote the file, or the state directory was cleared/moved.
Common situations: Loading before saving in a fresh environment, a typo in the name, or `stateDir` (from `resolveConfig()`) pointing somewhere unexpected after a config/env change.
Related errors
- File not found
- Skill "${name}" not found in any tier.
- Skill "${name}" not found.
- Skill "${name}" has no script.test.ts at ${testFile}
- Skill "${opts.skill.name}" missing script.ts at ${scriptPath
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/44cebfbe6da1ab24.
Report an issue: GitHub.