{"record":{"id":"f0d5d0396c77b986","repo":"tinyhumansai/openhuman","slug":"delete-failed","errorCode":"DELETE_FAILED","errorMessage":"${reason}","messagePattern":"\\$\\{reason\\}","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/services/artifactDownloadService.ts","lineNumber":330,"sourceCode":" * `ArtifactMeta` row in the workspace registry.\n *\n * Returns `{ ok: false, error }` on any transport or RPC error\n * (network drop, core gone, unknown id, file vanished). The core\n * treats \"missing meta\" / \"file already gone\" as success.\n */\nexport async function deleteArtifact(artifactId: string): Promise<DeleteArtifactOutcome> {\n  if (!artifactId.trim()) {\n    return { ok: false, code: 'MISSING_ARTIFACT_ID', error: 'artifact id missing' };\n  }\n  try {\n    await callCoreRpc<unknown>({\n      method: 'openhuman.ai_delete_artifact',\n      params: { artifact_id: artifactId },\n    });\n    return { ok: true };\n  } catch (err) {\n    const reason = err instanceof Error ? err.message : String(err);\n    return { ok: false, code: 'DELETE_FAILED', error: reason };\n  }\n}\n\nexport async function revealArtifactInFileManager(absolutePath: string): Promise<boolean> {\n  if (!isTauri()) return false;\n  if (!absolutePath.trim()) return false;\n  try {\n    // Use the plugin's typed binding — the raw `invoke('plugin:opener|\n    // reveal_item_in_dir', { path })` shape silently no-ops because the\n    // plugin expects `{ paths: [absolutePath] }` (array). The binding\n    // handles the wrap.\n    await revealItemInDir(absolutePath);\n    return true;\n  } catch (err) {\n    // Swallow — reveal is best-effort, the file is already saved.\n    console.warn('[artifact] revealItemInDir failed:', err);\n    return false;\n  }","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/services/artifactDownloadService.ts#L312-L348","documentation":"Returned when the openhuman.ai_delete_artifact core RPC itself throws - a transport-level failure (embedded core process gone, stale RPC port or bearer, HTTP error) or an RPC rejection such as unknown-method in a build where that surface is gated out. The core deliberately treats 'missing ArtifactMeta' and 'file already gone' as success, so DELETE_FAILED almost always means the RPC could not be completed at all, not that the target was absent.","triggerScenarios":"The core process crashed or was restarted while the UI held an old port or bearer; calling deleteArtifact before the embedded core reached ready state (boot race); a version or gating skew where the running core does not know the openhuman.ai_delete_artifact method.","commonSituations":"Deleting an artifact right after a core restart or app update; OPENHUMAN_CORE_REUSE_EXISTING pointing at a dead external core; dev iteration with a hot-reloaded frontend against a restarting core.","solutions":["Read the embedded error text: connection failures point to core availability, 'unknown method' to version or feature-gating skew.","Retry once after the core becomes ready again (restart_core_process or waiting for the ready signal) - boot races are the most common shape.","If the method is unknown, align frontend and core versions so the ai namespace is registered.","Only enable destructive UI actions after the core-ready gate has passed."],"exampleFix":"// before\nrows.remove(row); // optimistic\nawait deleteArtifact(id); // fire and forget\n\n// after\nrows.remove(row); // optimistic\nconst out = await deleteArtifact(id);\nif (!out.ok) {\n  rows.restore(row); // documented contract: re-insert on { ok: false }\n  showError(`Delete failed: ${out.error}`);\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"deleteArtifact returns DeleteArtifactOutcome rather than throwing. Follow the documented optimistic-UI contract: remove the row first, call deleteArtifact, and re-insert the row on { ok: false } so the user loses nothing when the core is unreachable.","preventionTips":["Enable destructive UI only after the core-ready gate passes.","Retry once after a core restart before surfacing the failure.","Log the embedded error text - it distinguishes transport failure from unknown-method skew."],"tags":["rpc","core","artifact","lifecycle","process-management"],"backgroundTag":"rpc-call-failed","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}