tinyhumansai/openhuman · error
RESOLVE_FAILED
RESOLVE_FAILED
Error message
${reason} What it means
resolveArtifactForExport calls callCoreRpc('openhuman.ai_get_artifact', { artifact_id }); if that RPC rejects - JSON-RPC error from the core (unknown artifact id, method error), transport failure, or the embedded core not yet ready - the rejection's message is captured verbatim as reason and returned as { ok: false, code: 'RESOLVE_FAILED', error: reason }. Like MISSING_ARTIFACT_ID this is a returned outcome, not a thrown exception.
Source
Thrown at app/src/services/artifactDownloadService.ts:203
async function resolveArtifactForExport(
artifactId: string,
fallbackTitle: string,
extension: string
): Promise<ResolveExportResult> {
if (!artifactId.trim()) {
return { ok: false, code: 'MISSING_ARTIFACT_ID', error: 'artifact id missing' };
}
let resolved: AiGetArtifactData;
try {
const raw = await callCoreRpc<AiGetArtifactData>({
method: 'openhuman.ai_get_artifact',
params: { artifact_id: artifactId },
});
resolved = raw ?? {};
} catch (err) {
const reason = err instanceof Error ? err.message : String(err);
return { ok: false, code: 'RESOLVE_FAILED', error: reason };
}
const sourcePath = resolved.absolute_path;
if (!sourcePath) {
return {
ok: false,
code: 'MISSING_ARTIFACT_PATH',
error: 'artifact path missing from core response',
};
}
// Prefer the persisted title (came from create_artifact's
// sanitized stem) but fall back to the caller-supplied hint.
const title = resolved.meta?.title?.trim() || fallbackTitle.trim() || 'artifact';
const ext = extension.trim().replace(/^\.+/, '');
// Guard against double extensions: if `title` already ends in the
// requested extension (case-insensitive, with any other extension also
// tolerated), don't append again. Prevents `deck.pptx.pptx` when theView on GitHub (pinned to 7491200858)
Solutions
- Read the embedded reason - it is the core RPC's own error message and distinguishes 'unknown artifact' from transport failures
- Verify the artifact still exists (re-render the owning message / list) before exporting
- For core-not-ready cases, retry once the core health check passes
- Check core logs for the ai_get_artifact handler if the reason is opaque
Defensive patterns
Strategy: try-catch
Type guard
const isResolveFailed = (o: DownloadArtifactOutcome): o is { ok: false; code: 'RESOLVE_FAILED'; error: string } =>
!o.ok && o.code === 'RESOLVE_FAILED'; Try / catch
const outcome = await downloadArtifact(artifactId, title, ext);
if (!outcome.ok) {
switch (outcome.code) {
case 'RESOLVE_FAILED':
// outcome.error is the core RPC's own message - show it, retry once if core was mid-start
showError(outcome.error);
break;
default:
showError(outcome.error);
}
} Prevention
- Check core health before export flows if the core is freshly started
- Log outcome.error verbatim - it carries the JSON-RPC reason and is the only detail you get
- Remember resolve failures are returned, not thrown: branch on ok/code rather than wrapping in try/catch
When it happens
Trigger: The artifact id does not exist core-side (deleted or from another workspace); the embedded core process is still starting or has died so relay_http_rpc fails; the RPC returns a JSON-RPC error object whose message becomes the reason string.
Common situations: Downloading an artifact right as a thread switches or the core restarts; artifact ids persisted from an older workspace; any core-side regression in ai_get_artifact surfacing as this generic wrapper with the core's message inside.
Related errors
- MISSING_ARTIFACT_ID
- MISSING_ARTIFACT_PATH
- oauthAuthReadinessUserMessage(quick.reason)
- OPENAI_CODEX_OAUTH_MISSING_AUTH_URL
- Model test RPC returned no result for ${workload} via ${prov
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/8f53956bb3b10c9c.
Report an issue: GitHub.