Hmbown/CodeWhale · error · Error

Restore points returned HTTP ${response.statusCode}.

Error message

Restore points returned HTTP ${response.statusCode}.

What it means

The source bundle of a local install has a manifest, but PluginManifest::validate_from_path rejected it (parse error or schema violation) before any bytes were copied to staging. Validating first means a bad manifest never reaches the user plugins directory, and the underlying {error} from the validator is chained so the specific field problem is visible in the full error chain.

Source

Thrown at extensions/vscode/src/runtime.ts:136

  if (response.statusCode !== 200) {
    throw new Error(`Thread summary returned HTTP ${response.statusCode}.`);
  }

  return readThreadSummaries(response.body);
}

export async function listSnapshots(config: RuntimeConfig, limit = 8): Promise<SnapshotEntry[]> {
  const baseUrl = runtimeBaseUrl(config);
  const response = await requestJson(
    `${baseUrl}/v1/snapshots?limit=${encodeURIComponent(String(limit))}`,
    config.token,
  );

  if (response.statusCode === 401) {
    throw new Error("Restore points require the runtime bearer token.");
  }
  if (response.statusCode !== 200) {
    throw new Error(`Restore points returned HTTP ${response.statusCode}.`);
  }

  return readSnapshots(response.body);
}

export function startRuntimeTerminal(config: RuntimeConfig): vscode.Terminal {
  const terminal = vscode.window.createTerminal("CodeWhale Runtime");
  const args = [
    "serve",
    "--http",
    "--host",
    shellQuote(config.host),
    "--port",
    String(config.port),
  ];
  if (config.token) {
    args.push("--auth-token", shellQuote(config.token));
  }

View on GitHub (pinned to 8880682c63)

Solutions

  1. Read the chained {error} — it names the exact parse/validation failure; fix that field in the source manifest.
  2. Validate the manifest yourself first: parse plugin.json with a JSON linter or run PluginManifest::validate_from_path on it.
  3. If the bundle came from a third party, check for an updated release compatible with the current manifest schema.

Example fix

# before: plugin.json is invalid JSON (trailing comma)
{ "plugin": { "name": "demo", } }

# after
{ "plugin": { "name": "demo" } }
Defensive patterns

Strategy: validation

Validate before calling

let manifest = source.join("plugin.json");
let raw = std::fs::read_to_string(&manifest)
    .with_context(|| format!("read {}", manifest.display()))?;
serde_json::from_str::<serde_json::Value>(&raw)
    .map_err(|e| anyhow::anyhow!("source manifest is not valid JSON: {e}"))?;
stage_local_copy(source, user_plugins_dir, max_size)?;

Type guard

fn manifest_parses(bundle: &Path) -> bool {
    crate::plugins::agent_plugin::resolve_manifest_path(bundle)
        .and_then(|m| std::fs::read_to_string(m).ok())
        .map(|raw| serde_json::from_str::<serde_json::Value>(&raw).is_ok()
            || raw.parse::<toml::Value>().is_ok())
        .unwrap_or(false)
}

Try / catch

match stage_local_copy(source, plugins_dir, max_size) {
    Ok(staged) => staged,
    Err(e) if e.to_string().contains("source is not a valid plugin bundle") =>
        return Err(e).context(format!("fix the manifest in {} first", source.display()))),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: stage_local_copy on a directory whose plugin.json/plugin.toml is malformed (bad JSON/TOML syntax, missing [plugin].name, invalid structure) — validation runs immediately after the manifest is located, before canonicalize/copy.

Common situations: Hand-edited manifests with syntax errors; bundles authored for a different manifest schema version; manifests truncated by a partial download; TOML manifests using the wrong table name.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/f606b4bc0601e840. Report an issue: GitHub.