{"record":{"id":"aac5f79056eb4c10","repo":"BabylonJS/Babylon.js","slug":"switch-should-have-a-single-configuration-object","errorCode":null,"errorMessage":"Switch should have a single configuration object, the cases array","messagePattern":"Switch should have a single configuration object, the cases array","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.ts","lineNumber":1120,"sourceCode":"                const onlyIntegers = cases.value.every((caseValue) => {\n                    // case value should be an integer. Since Number.isInteger(1.0) is true, we need to check if toString has only digits.\n                    return typeof caseValue === \"number\" && /^-?\\d+$/.test(caseValue.toString());\n                });\n                if (!onlyIntegers) {\n                    Logger.Warn(\"Switch cases should be integers. Using empty array instead.\");\n                    cases.value = [] as number[];\n                    return { valid: true };\n                }\n                // check for duplicates\n                const uniqueCases = new Set(cases.value);\n                cases.value = Array.from(uniqueCases) as number[];\n            }\n            return { valid: true };\n        },\n        extraProcessor(gltfBlock, declaration, _mapping, _arrays, serializedObjects) {\n            // convert all names of output flow to out_$1 apart from \"default\"\n            if (declaration.op !== \"flow/switch\" || !gltfBlock.flows || Object.keys(gltfBlock.flows).length === 0) {\n                throw new Error(\"Switch should have a single configuration object, the cases array\");\n            }\n            const serializedObject = serializedObjects[0];\n            serializedObject.signalOutputs.forEach((output) => {\n                if (output.name !== \"default\") {\n                    output.name = \"out_\" + output.name;\n                }\n            });\n            return serializedObjects;\n        },\n    },\n    \"flow/while\": {\n        blocks: [FlowGraphBlockNames.WhileLoop],\n        outputs: {\n            flows: {\n                loopBody: { name: \"executionFlow\" },\n            },\n        },\n    },","sourceCodeStart":1102,"sourceCodeEnd":1138,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.ts#L1102-L1138","documentation":"The flow/switch extraProcessor expects the glTF switch block to declare output flows (the case branches). It throws this error when the declaration op is not flow/switch or when gltfBlock.flows is missing/empty, because it needs to rename each non-default output flow to out_<case> on the serialized block.","triggerScenarios":"Loading an interactivity graph with a switch block that has no \"flows\" object, an empty flows map, or a block mis-mapped so this processor runs against a non-switch declaration.","commonSituations":"Exporter emitting switch with zero cases; hand-pruned JSON removing flows; custom declaration maps wiring the wrong op to the switch processor.","solutions":["Ensure the flow/switch block defines at least one entry in its \"flows\" object (plus optional \"default\")","Re-export the asset with a compliant KHR_interactivity exporter","Fix custom declaration mapping so this processor only handles flow/switch"],"exampleFix":"// before\n{ \"op\": \"flow/switch\", \"configuration\": { \"cases\": { \"value\": [0,1] } } } // no flows\n// after\n{ \"op\": \"flow/switch\", \"flows\": { \"0\": {}, \"1\": {} }, \"configuration\": { \"cases\": { \"value\": [0,1] } } }","handlingStrategy":"validation","validationCode":"function validateSwitchBlock(block) {\n  return typeof block.flows === \"object\" && block.flows !== null && Object.keys(block.flows).length > 0;\n}\n// verify each flow/switch block declares at least one flow before loading","typeGuard":"const hasFlows = (b: { flows?: Record<string, unknown> | null }): b is { flows: Record<string, unknown> } => !!b.flows && Object.keys(b.flows).length > 0;","tryCatchPattern":"try {\n  await loader.loadAsync(url);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"Switch should have a single configuration\")) {\n    console.error(\"flow/switch block is missing its flows (cases) object.\");\n  } else throw e;\n}","preventionTips":["Ensure exporters always emit the flows map for switch blocks","Validate interactivity JSON schema in the asset pipeline","Test parse of all interactivity assets after exporter updates"],"tags":["gltf","interactivity","flow-graph","validation"],"backgroundTag":"gltf-interactivity-invalid-configuration","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}