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 the

View on GitHub (pinned to 7491200858)

Solutions

  1. Read the embedded reason - it is the core RPC's own error message and distinguishes 'unknown artifact' from transport failures
  2. Verify the artifact still exists (re-render the owning message / list) before exporting
  3. For core-not-ready cases, retry once the core health check passes
  4. 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

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


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/8f53956bb3b10c9c. Report an issue: GitHub.