tinyhumansai/openhuman · error

MISSING_ARTIFACT_ID

MISSING_ARTIFACT_ID

Error message

artifact id missing

What it means

resolveArtifactForExport trims the artifactId argument; if it is empty or whitespace-only it returns (does NOT throw) a result object { ok: false, code: 'MISSING_ARTIFACT_ID', error: 'artifact id missing' }. Callers of downloadArtifact / the Save-As path must branch on ok, not use try/catch - this is a typed outcome, part of the DownloadArtifactOutcome/ResolveExportResult discriminated union.

Source

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

    return { ok: true, artifacts };
  } catch (err) {
    const reason = err instanceof Error ? err.message : String(err);
    return { ok: false, artifacts: [], error: reason };
  }
}

/**
 * Resolve an artifact's absolute on-disk path (via `ai_get_artifact`)
 * and build the suggested filename. Shared by the Save-As and Downloads
 * export paths so both apply identical title/extension handling.
 */
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,

View on GitHub (pinned to 7491200858)

Solutions

  1. Pass the real artifact id from the artifact record (the same id accepted by openhuman.ai_get_artifact)
  2. Guard at the call site: hide/disable the download control when the id is blank
  3. If the id should exist, trace why the owning payload lacks it - this error is always a caller-side data bug

Example fix

// before
downloadArtifact(artifact.artifactId ?? '', artifact.title, 'md');

// after - do not offer the action without an id
if (!artifact.artifactId?.trim()) return null; // or hide the button
return <DownloadButton onClick={() => void downloadArtifact(artifact.artifactId!, artifact.title, 'md')} />;
Defensive patterns

Strategy: validation

Validate before calling

// Guard before calling into the export path
if (typeof artifactId !== 'string' || !artifactId.trim()) {
  // do not open the dialog / do not call downloadArtifact
  return;
}

Type guard

// Narrow the outcome the service returns
const isMissingId = (o: DownloadArtifactOutcome): o is { ok: false; code: 'MISSING_ARTIFACT_ID'; error: string } =>
  !o.ok && o.code === 'MISSING_ARTIFACT_ID';

Prevention

When it happens

Trigger: Calling downloadArtifact or the Save-As flow with an empty string, whitespace, or an undefined id stringified - e.g. an artifact row whose artifactId field is missing in the message payload that spawned the download button.

Common situations: UI rendering a download button for an artifact reference before the id arrives; artifact objects built from partial RPC data where artifact_id was never set; defensive default '' values flowing into the export path.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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