Hmbown/CodeWhale · error · Error
Thread summary returned HTTP ${response.statusCode}.
Error message
Thread summary returned HTTP ${response.statusCode}. What it means
After the staged manifest validates, its [plugin].name is checked by validate_skill_name_segment because that name becomes the installation directory under the user plugins dir. The name is rejected when empty, whitespace-padded or containing any whitespace, equal to '.' or '..', containing '/' or '\\', or otherwise not a single normal path component. This is the staged-time twin of the plugin_target_path guard, failing before any copy happens.
Source
Thrown at extensions/vscode/src/runtime.ts:119
version,
};
}
export async function listThreadSummaries(
config: RuntimeConfig,
limit = 8,
): Promise<ThreadSummary[]> {
const baseUrl = runtimeBaseUrl(config);
const response = await requestJson(
`${baseUrl}/v1/threads/summary?limit=${encodeURIComponent(String(limit))}`,
config.token,
);
if (response.statusCode === 401) {
throw new Error("Thread summaries require the runtime bearer token.");
}
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}.`);
}View on GitHub (pinned to 8880682c63)
Solutions
- Set [plugin].name to a single path-safe slug: no whitespace, no separators, not '.'/'..' (e.g. "data-sync").
- Use a description/title field for the human-readable name and keep the name field machine-safe.
- Lint manifests before publishing: reject names that trim unevenly or contain path characters.
Example fix
// before (plugin.json)
{ "plugin": { "name": "Data Sync Plugin" } }
// after
{ "plugin": { "name": "data-sync", "description": "Data Sync Plugin" } } Defensive patterns
Strategy: validation
Validate before calling
let name = validated.manifest.plugin.name.clone();
if !is_safe_plugin_name(&name) {
anyhow::bail!("[plugin].name must be one path-safe segment, got '{name}'");
} Type guard
fn is_safe_plugin_name(name: &str) -> bool {
!name.is_empty()
&& name.trim() == name
&& !name.chars().any(char::is_whitespace)
&& !matches!(name, "." | "..")
&& !name.contains('/') && !name.contains('\\')
} Try / catch
match validate_staged(&staged_path) {
Ok(v) => v,
Err(e) if e.to_string().contains("[plugin].name is not a safe directory name") =>
return Err(e).context("rename the plugin in its manifest to a slug and reinstall"),
Err(e) => return Err(e),
} Prevention
- Use slug-style names in [plugin].name; keep display titles in description.
- Trim and inspect names for hidden whitespace when copying from documentation.
- Lint third-party bundles with the segment validator before distributing them.
When it happens
Trigger: The staged bundle's plugin.json has a name like "Data Sync", "tools/exporter", "..", or an empty string; validate_staged extracts the name and the segment check fails.
Common situations: Authors putting display names into [plugin].name; copy-pasting a name with a trailing newline or space; third-party bundles authored against looser conventions; names containing Windows separators.
Related errors
- pipeline(): expected an array of items
- Thread summaries require the runtime bearer token.
- Restore points require the runtime bearer token.
- Restore points returned HTTP ${response.statusCode}.
- parallel(): max ${MAX_ITEMS} items per call
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/424af30458bf2f60.
Report an issue: GitHub.