different-ai/openwork · error

workflow_invalid_schema

workflow_invalid_schema

Error message

workflow_invalid_schema:${parsed.message}

What it means

Before persisting, saveWorkflow assembles a normalized payload (language, optional inputSchema/outputSchema, exampleInput from currentInput, requiredCapabilities) and validates it with parseCodemodeScriptPayload. If the payload fails parsing/schema validation, the error 'workflow_invalid_schema:<message>' is thrown with the underlying parser message appended. The root cause detail is in the thrown message after the colon.

Source

Thrown at ee/apps/den-api/src/workflows.ts:647

    const resolved = manifestByPath.get(call.name)
    if (!resolved) throw new Error(`workflow_capability_unavailable:${call.name}`)
    if (resolved.readOnly !== true) throw new Error(`workflow_requires_read_only_capabilities:${call.name}`)
    if (!requiredCapabilities.some((entry) => entry.scriptPath === resolved.scriptPath)) {
      requiredCapabilities.push({
        capabilityName: resolved.capabilityName,
        scriptPath: resolved.scriptPath,
      })
    }
  }
  const normalizedPayloadJson = {
    language: "codemode-js",
    ...(input.workflow.inputSchema === undefined ? {} : { inputSchema: input.workflow.inputSchema }),
    ...(input.workflow.outputSchema === undefined ? {} : { outputSchema: input.workflow.outputSchema }),
    ...(input.workflow.currentInput === undefined ? {} : { exampleInput: input.workflow.currentInput }),
    requiredCapabilities,
  }
  const parsed = parseCodemodeScriptPayload(normalizedPayloadJson)
  if (!parsed.ok) throw new Error(`workflow_invalid_schema:${parsed.message}`)
  if (parsed.payload.inputSchema) {
    const validation = validateCodemodeScriptInput(parsed.payload.inputSchema, input.workflow.currentInput)
    if (!validation.ok) throw new Error("workflow_current_input_invalid")
  }

  return db.transaction(async (tx) => {
    const plugins = requestedPluginId
      ? await tx.select().from(PluginTable).where(and(
          eq(PluginTable.id, requestedPluginId),
          eq(PluginTable.organizationId, organizationId),
          eq(PluginTable.status, "active"),
          isNull(PluginTable.deletedAt),
        )).limit(1).for("update")
      : await tx.select().from(PluginTable).where(and(
          eq(PluginTable.organizationId, organizationId),
          eq(PluginTable.createdByOrgMembershipId, ownerMemberId),
          eq(PluginTable.name, DEFAULT_WORKFLOWS_PLUGIN_NAME),
          eq(PluginTable.status, "active"),

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Read the parser detail in the error message after 'workflow_invalid_schema:' and fix the schema accordingly
  2. Pass inputSchema/outputSchema as plain JSON Schema objects, not strings
  3. Validate the schema locally with the same JSON Schema validator the parser uses before calling saveWorkflow
  4. Remove the optional schema fields to confirm the rest of the payload parses, then add them back incrementally

Example fix

// before
inputSchema: JSON.stringify({ type: 'object', properties: { q: { type: 'string' } } })
// after
inputSchema: { type: 'object', properties: { q: { type: 'string' } }, required: ['q'] }
Defensive patterns

Strategy: validation

Validate before calling

const payload = { language: 'codemode-js', inputSchema: myInputSchema, outputSchema: myOutputSchema, exampleInput: myInput }
const parsed = parseCodemodeScriptPayload(payload) // run the same parser client-side first
if (!parsed.ok) throw new Error(`fix schema before saving: ${parsed.message}`)

Type guard

function isJsonObjectSchema(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v) && (v as { type?: unknown }).type === 'object'
}

Try / catch

try {
  await saveWorkflow(input)
} catch (err) {
  const m = /^workflow_invalid_schema:(.+)$/.exec(err instanceof Error ? err.message : '')
  if (m) console.error(`Schema rejected: ${m[1]}`)
}

Prevention

When it happens

Trigger: Providing inputSchema or outputSchema that parseCodemodeScriptPayload rejects (not a valid JSON schema object, wrong shape/type), or a payload combination the parser deems invalid.

Common situations: Hand-written JSON Schema with typos or non-standard keywords; passing a schema as a JSON string instead of an object; schemas built by another tool that emit unsupported constructs; currentInput type mismatching the declared schema shape in ways the parser flags.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/884a32075516686d. Report an issue: GitHub.