linshenkx/prompt-optimizer · error · Error
Missing optimizerTarget.subModeKey
Error message
Missing optimizerTarget.subModeKey
What it means
After schema checks pass, the importer requires routing metadata: data.optimizerTarget.subModeKey must exist, be a string, and be non-empty after trimming. This key tells the importer which optimizer sub-mode the prompt targets; without it the imported prompt cannot be routed.
Source
Thrown at packages/ui/src/composables/app/useAppPromptGardenImport.ts:542
const parseV1 = (data: unknown): FetchedPrompt => {
if (!isPlainObject(data)) {
throw new Error('Garden response must be a JSON object')
}
if (data.schema !== 'prompt-garden.prompt.v1') {
throw new Error('Unsupported Garden response schema')
}
if (data.schemaVersion !== 1) {
throw new Error('Unsupported Garden response schemaVersion')
}
const optimizerTarget = isPlainObject(data.optimizerTarget) ? data.optimizerTarget : null
const optimizerTargetKey =
optimizerTarget && typeof optimizerTarget.subModeKey === 'string'
? optimizerTarget.subModeKey.trim()
: ''
if (!optimizerTargetKey) {
throw new Error('Missing optimizerTarget.subModeKey')
}
const prompt = isPlainObject(data.prompt) ? data.prompt : null
const format = prompt && (prompt.format === 'text' || prompt.format === 'messages')
? (prompt.format as 'text' | 'messages')
: null
if (!format) {
throw new Error('Missing prompt.format')
}
let promptText: string | undefined
let promptMessages: ConversationMessage[] | undefined
if (format === 'text') {
const t = prompt && typeof prompt.text === 'string' ? prompt.text : ''
if (!t.trim()) {
throw new Error('Empty prompt.text')
}
promptText = tView on GitHub (pinned to 3e677b1d9f)
Solutions
- Add an optimizerTarget object with a non-empty string subModeKey to the payload (e.g. {"optimizerTarget":{"subModeKey":"default"}})
- Verify the export flow on the Garden side actually captures the sub-mode key
- If the key is genuinely optional for your use case, patch parseV1 to fall back to a default instead of throwing
Example fix
// before
{ "prompt": { ... }, "optimizerTarget": {} }
// after
{ "prompt": { ... }, "optimizerTarget": { "subModeKey": "quality" } } Defensive patterns
Strategy: type-guard
Validate before calling
const key = raw?.optimizerTarget?.subModeKey
if (typeof key !== 'string' || !key.trim()) { /* block import with clear message */ } Type guard
const hasOptimizerTarget = (d: unknown): d is { optimizerTarget: { subModeKey: string } } =>
isPlainObject(d) && isPlainObject(d.optimizerTarget) && typeof d.optimizerTarget.subModeKey === 'string' && d.optimizerTarget.subModeKey.trim() !== '' Try / catch
catch (e) { if (e.message === 'Missing optimizerTarget.subModeKey') promptUserToPickSubMode(); else throw e } Prevention
- Require sub-mode selection before exporting prompts
- Validate exports on the Garden side before publishing
- Include optimizerTarget in test fixtures
When it happens
Trigger: optimizerTarget is missing, not a plain object, subModeKey is absent/null/number, or is a whitespace-only string after trim().
Common situations: Prompts exported without an optimizer target selected; older exports that predate the optimizerTarget field; upstream data corruption; fixture prompts copied without the routing block.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- ${label} testCaseId must not be empty.
- Function mode (functionMode) cannot be empty
- CONFIG_INVALID
- Model config cannot be empty
- User prompt is required
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/1a49facc3d47b5f3.
Report an issue: GitHub.