{"record":{"id":"147b99b8004aa854","repo":"ruvnet/ruflo","slug":"invalid-platform-platformraw-in-worker-spec","errorCode":null,"errorMessage":"Invalid platform \"${platformRaw}\" in --worker spec \"${spec}\". Use \"claude\" or \"codex\".","messagePattern":"Invalid platform \"(.+?)\" in --worker spec \"(.+?)\"\\. Use \"claude\" or \"codex\"\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/codex/src/dual-mode/cli.ts","lineNumber":280,"sourceCode":" */\nexport function parseWorkerSpecs(specs: string[], parallel: boolean): WorkerConfig[] {\n  const usedIds = new Set<string>();\n  const workers: WorkerConfig[] = [];\n\n  specs.forEach((spec, index) => {\n    const firstColon = spec.indexOf(':');\n    const secondColon = firstColon >= 0 ? spec.indexOf(':', firstColon + 1) : -1;\n    if (firstColon < 0 || secondColon < 0) {\n      throw new Error(`Invalid --worker spec \"${spec}\". Expected \"<platform>:<role>:<prompt>\" (platform = claude|codex).`);\n    }\n    const platformRaw = spec.slice(0, firstColon).trim().toLowerCase();\n    const role = spec.slice(firstColon + 1, secondColon).trim() || `worker-${index + 1}`;\n    const prompt = spec.slice(secondColon + 1).trim();\n    if (!prompt) {\n      throw new Error(`Invalid --worker spec \"${spec}\". Missing prompt after \"<platform>:<role>:\".`);\n    }\n    if (platformRaw !== 'claude' && platformRaw !== 'codex') {\n      throw new Error(`Invalid platform \"${platformRaw}\" in --worker spec \"${spec}\". Use \"claude\" or \"codex\".`);\n    }\n    const platform: 'claude' | 'codex' = platformRaw;\n\n    // Derive a unique id from the role.\n    const base = role.replace(/\\s+/g, '-');\n    let id = base;\n    let suffix = 2;\n    while (usedIds.has(id)) { id = `${base}-${suffix++}`; }\n    usedIds.add(id);\n\n    const worker: WorkerConfig = { id, platform, role, prompt };\n    const prev = workers[workers.length - 1];\n    if (!parallel && prev) {\n      worker.dependsOn = [prev.id];\n    }\n    workers.push(worker);\n  });\n","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/codex/src/dual-mode/cli.ts#L262-L298","documentation":"parseWorkerSpecs() variant thrown when the platform segment (text before the first colon, trimmed and lowercased) is neither 'claude' nor 'codex'. The dual-mode orchestrator only knows how to spawn these two worker platforms, and the platform decides which command template and prompt wrapper is used, so any other value is rejected before a worker is created.","triggerScenarios":"(1) `--worker \"gpt:coder:...\"` or `--worker \"cursor:coder:...\"` — unsupported platform names; (2) typos like \"calude\" or \"codez\"; (3) segments in the wrong order, e.g. putting the role first (\"reviewer:claude:...\") so 'reviewer' is parsed as the platform.","commonSituations":"Assuming any CLI/tool name works as a worker; transposing segment order when writing specs by hand; naming the platform after a model ('opus', 'gpt-4') instead of the two supported harnesses.","solutions":["Use exactly `claude` or `codex` as the first segment: `--worker \"codex:coder:Implement the endpoint\"`.","Double-check segment order — platform comes first, then role, then prompt.","The check is case-insensitive and whitespace-tolerant (trimmed/lowered), so fix only the value itself, not casing.","If you need a different tool, run it outside dual-mode or extend WorkerConfig platform support in code."],"exampleFix":"# before\n$ dual-mode collaborate --worker \"opus:coder:Write the service layer\"\nError: Invalid platform \"opus\" in --worker spec \"opus:coder:Write the service layer\". Use \"claude\" or \"codex\".\n\n# after\n$ dual-mode collaborate --worker \"claude:coder:Write the service layer\"","handlingStrategy":"validation","validationCode":"const PLATFORMS = new Set(['claude', 'codex']);\nfunction platformOf(spec: string): string | null {\n  const first = spec.indexOf(':');\n  if (first < 0) return null;\n  const p = spec.slice(0, first).trim().toLowerCase();\n  return PLATFORMS.has(p) ? p : null;\n}\nfor (const spec of specs) {\n  if (!platformOf(spec)) throw new Error(`platform must be claude|codex in: ${spec}`);\n}\nconst workers = parseWorkerSpecs(specs, parallel);","typeGuard":"function isWorkerPlatform(v: unknown): v is 'claude' | 'codex' {\n  return v === 'claude' || v === 'codex';\n}","tryCatchPattern":"try {\n  const workers = parseWorkerSpecs(specs, parallel);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Invalid platform')) {\n    throw new Error('segment order is <platform>:<role>:<prompt> with platform claude or codex — check you did not lead with the role');\n  }\n  throw err;\n}","preventionTips":["Memorize the segment order: platform first — most bad-platform errors are transposed specs","The check is trim+lowercase, so casing never helps; only the values 'claude'/'codex' are accepted","Model names (opus, gpt-4) are not platforms — pick the harness that runs the model","Restrict spec generation to a helper that takes platform as a union type"],"tags":["dual-mode","cli-arguments","platform-validation"],"backgroundTag":"invalid-cli-argument-format","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}