tinyhumansai/openhuman · error

MISSING_ARTIFACT_PATH

MISSING_ARTIFACT_PATH

Error message

artifact path missing from core response

What it means

The openhuman.ai_get_artifact RPC succeeded, but the returned record has no absolute_path, so resolveArtifactForExport returns { ok: false, code: 'MISSING_ARTIFACT_PATH', error: 'artifact path missing from core response' }. The contract expects every artifact to carry its on-disk absolute path; absence means a version-skewed or degraded core response, not a caller bug.

Source

Thrown at app/src/services/artifactDownloadService.ts:210

  }

  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
  // persisted title is `deck.pptx` and the caller passes `'pptx'`.
  const titleHasExtension = /\.[^./\\]+$/.test(title);
  const titleHasSameExt = ext.length > 0 && title.toLowerCase().endsWith(`.${ext.toLowerCase()}`);
  const filename = ext && !titleHasExtension && !titleHasSameExt ? `${title}.${ext}` : title;

  return { ok: true, sourcePath, filename };
}

View on GitHub (pinned to 7491200858)

Solutions

  1. Update / restart the core so the UI and ai_get_artifact response shapes match
  2. Verify the artifact opens elsewhere (chat view) - if it renders, the record is fine and the path loss is the skew
  3. If the file was legitimately removed, delete the artifact record so the download affordance disappears
  4. Check the raw RPC response in the network/devtools to confirm absolute_path is truly absent vs empty string

Example fix

// before - trust the record shape
const resolved = await callCoreRpc<AiGetArtifactData>(...);
const sourcePath = resolved.absolute_path;

// after - narrow before use (what the service itself does)
const resolved = await callCoreRpc<AiGetArtifactData>(...);
if (typeof resolved?.absolute_path !== 'string' || !resolved.absolute_path) {
  return { ok: false, code: 'MISSING_ARTIFACT_PATH', error: 'artifact path missing from core response' };
}
Defensive patterns

Strategy: type-guard

Type guard

// Narrow the raw RPC record before trusting it
const hasAbsolutePath = (r: AiGetArtifactData | null | undefined): r is AiGetArtifactData & { absolute_path: string } =>
  typeof r?.absolute_path === 'string' && r.absolute_path.length > 0;

const raw = await callCoreRpc<AiGetArtifactData>({ method: 'openhuman.ai_get_artifact', params: { artifact_id: id } });
if (!hasAbsolutePath(raw)) { /* MISSING_ARTIFACT_PATH path */ }

Prevention

When it happens

Trigger: UI newer than the embedded core (older core omits absolute_path from ai_get_artifact); an artifact record whose file was deleted from disk / never written but whose row still resolves; a non-file artifact type returned for a download request.

Common situations: Running the Vite dev UI against a stale built core; artifacts left half-written after a crash; switching workspaces while an export is in flight; core schema drift after an update where the field was renamed.

Related errors


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