screenpipe/screenpipe · error · Error
POST /artifacts/register returned ${res.status}
Error message
POST /artifacts/register returned ${res.status} What it means
save_artifact writes the content to a session temp file, then POSTs it to the local engine at /artifacts/register. Any non-OK HTTP status from that endpoint is converted to this error carrying the status code. The temp file is already written, but registration (indexing/visibility in the Artifacts library) failed.
Source
Thrown at crates/screenpipe-core/assets/acp/screenpipe-tools.mjs:681
mkdirSync(tmpDir, { recursive: true });
const tmpPath = join(tmpDir, filename);
if (encoding === "base64") {
writeFileSync(tmpPath, Buffer.from(content, "base64"));
} else {
writeFileSync(tmpPath, content, "utf-8");
}
const res = await fetch(`${apiBase()}/artifacts/register`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
source: sessionId,
source_type: "chat",
title: args?.title || filename.replace(extname(filename), "").replace(/[-_]/g, " "),
kind,
file_path: tmpPath,
}),
});
if (!res.ok) throw new Error(`POST /artifacts/register returned ${res.status}`);
return JSON.stringify({ status: "saved", filename, kind });
},
},
{
name: "sp_web_search",
description:
"Search the public internet via Google Search. Use ONLY for public, external information the user explicitly asks about (current events, news, public people or companies, public product docs). Do NOT use it for the user's own screenpipe data. When unsure, do not search. Returns results with sources.",
inputSchema: {
type: "object",
properties: {
query: { type: "string", description: "The search query" },
},
required: ["query"],
additionalProperties: false,
},
async run(args) {
const query = String(args?.query ?? "").trim();
if (!query) throw new Error("query is required");View on GitHub (pinned to 4ebf712990)
Solutions
- Check the screenpipe engine is running and apiBase() points at the right host/port.
- Read the status: 401/403 → re-authenticate the app; 404 → update the engine to a version with /artifacts/register; 5xx → check engine logs for the registration failure.
- Retry the save_artifact call once the engine is healthy; the temp file is reused/upserted by session.
Defensive patterns
Strategy: try-catch
Validate before calling
const res = await fetch(`${apiBase()}/health`); if (!res.ok) throw new Error("engine not ready; abort save_artifact"); Try / catch
try { await save_artifact(args) } catch (e) { if (/POST \/artifacts\/register returned (\d+)/.test(e.message)) { const status = +RegExp.$1; if (status >= 500 || status === 429) retryWithBackoff(); else reportToUser(status); } else throw e } Prevention
- Confirm the engine is running before agent sessions
- Pin engine versions that include /artifacts/register
- Log response status + engine logs on failure
When it happens
Trigger: Local screenpipe API down or restarting (ECONNREFUSED would surface as fetch rejection; other statuses here), 401 when auth token is stale, 404 when the engine version lacks /artifacts/register, 500 on engine-side write/index failure.
Common situations: Engine not yet started or updated while the agent session is running; port mismatch between apiBase() and the running server; backend bug rejecting the kind/file_path payload.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- otter returned {}: {}
- workflowy auth failed ({}): {}
- team skill API {}{}: {}
- web search failed (${res.status})${detail ? `: ${detail}` :
- failed to read OAuth metadata from {}: {}
AI-assisted analysis of screenpipe/screenpipe@4ebf712990 (2026-09-01).
Data as JSON: /api/errors/b4c66922a202a2d5.
Report an issue: GitHub.