nexu-io/open-design · warning · Error

artifactType must be one of

Error message

artifactType must be one of: ${Object.keys(openDesignBriefCatalog).join(', ')}

What it means

readArtifactType rejects any value that is not a string key of openDesignBriefCatalog (packages/contracts/src/api/brief.ts), which defines exactly eight artifact types such as website and product-prototype. The thrown message enumerates the accepted keys at runtime, so the canonical list is whatever the current catalog exposes.

Solutions

  1. Pass one of the keys printed in the error message.
  2. Source the allowed set from OPEN_DESIGN_BRIEF_ARTIFACT_TYPES in @open-design/contracts instead of hardcoding.
  3. Align the contracts dependency version with the daemon.

Example fix

// before
collect_brief({ artifactType: 'web-site' }) // typo -> throws [364]

// after
collect_brief({ artifactType: 'website' })
Defensive patterns

Strategy: type-guard

Validate before calling

import { OPEN_DESIGN_BRIEF_ARTIFACT_TYPES } from '@open-design/contracts';
const valid = new Set(OPEN_DESIGN_BRIEF_ARTIFACT_TYPES);
if (!valid.has(artifactType)) {
  throw new Error(`artifactType must be one of: ${[...valid].join(', ')}`);
}

Type guard

import { OPEN_DESIGN_BRIEF_ARTIFACT_TYPES } from '@open-design/contracts';
function isArtifactType(v: unknown): v is OpenDesignBriefArtifactType {
  return typeof v === 'string' && OPEN_DESIGN_BRIEF_ARTIFACT_TYPES.includes(v as any);
}

Prevention

When it happens

Trigger: Passing artifactType as undefined, a number, an empty string, a typo, or a value from an older or newer version whose catalog keys differ.

Common situations: Version skew between the contracts package the caller hardcoded and the daemon's catalog; free-text artifactType supplied by an LLM.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/743be0530131c3e7. Report an issue: GitHub.

Appendix: source

Thrown at apps/daemon/src/mcp-brief.ts:510

          ? { externalPluginContext: draft.externalPluginContext }
          : {}),
      };
      draft.confirmation = confirmation;
      draft.confirmationAnswersDigest = confirmationAnswersDigest;
      if (draft.pluginWorkflowId && draft.briefState !== 'skipped') {
        draft.briefState = 'confirmed';
      }
      return confirmation;
    },
  };
}

function readArtifactType(value: unknown): OpenDesignBriefArtifactType {
  if (
    typeof value !== 'string'
    || !Object.hasOwn(openDesignBriefCatalog, value)
  ) {
    throw new Error(
      `artifactType must be one of: ${Object.keys(openDesignBriefCatalog).join(', ')}`,
    );
  }
  return value as OpenDesignBriefArtifactType;
}

export function readBriefLocale(value: unknown): LocalMcpBriefLocale {
  if (typeof value !== 'string' || value.trim().length === 0) return 'en';
  const normalized = value.trim().replaceAll('_', '-').toLowerCase();
  if (normalized === 'zh' || normalized === 'zh-cn' || normalized.startsWith('zh-hans')) {
    return 'zh-CN';
  }
  if (
    normalized === 'zh-tw'
    || normalized === 'zh-hk'
    || normalized === 'zh-mo'
    || normalized.startsWith('zh-hant')
  ) {

View on GitHub (pinned to 5be4028344)