{"record":{"id":"f310a3295b1ea055","repo":"BabylonJS/Babylon.js","slug":"source-block-connection-outputblock-not-found","errorCode":null,"errorMessage":"Source block ${connection.outputBlock} not found","messagePattern":"Source block (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/smartFilters/src/serialization/smartFilterDeserializer.ts","lineNumber":95,"sourceCode":"        serializedSmartFilter.blocks.forEach((serializedBlock: ISerializedBlockV1) => {\r\n            blockDeserializationWork.push(\r\n                this._deserializeBlockV1Async(smartFilter, serializedBlock, engine, blockDefinitionsWhichCouldNotBeDeserialized, blockIdMap, blockNameMap)\r\n            );\r\n        });\r\n        await Promise.all(blockDeserializationWork);\r\n\r\n        // If any block definitions could not be deserialized, throw an error\r\n        if (blockDefinitionsWhichCouldNotBeDeserialized.length > 0) {\r\n            throw new Error(`Could not deserialize the following block definitions: ${blockDefinitionsWhichCouldNotBeDeserialized.join(\", \")}`);\r\n        }\r\n\r\n        // Deserialize the connections\r\n        serializedSmartFilter.connections.forEach((connection: ISerializedConnectionV1) => {\r\n            // Find the source block and its connection point's connectTo function\r\n            const sourceBlock = typeof connection.outputBlock === \"string\" ? blockNameMap.get(connection.outputBlock) : blockIdMap.get(connection.outputBlock);\r\n\r\n            if (!sourceBlock) {\r\n                throw new Error(`Source block ${connection.outputBlock} not found`);\r\n            }\r\n            const sourceConnectionPoint = sourceBlock.outputs.find((output) => output.name === connection.outputConnectionPoint);\r\n            if (!sourceConnectionPoint || typeof sourceConnectionPoint.connectTo !== \"function\") {\r\n                throw new Error(`Block ${connection.outputBlock} does not have an connection point named ${connection.outputConnectionPoint}`);\r\n            }\r\n            const sourceConnectToFunction = sourceConnectionPoint.connectTo.bind(sourceConnectionPoint);\r\n\r\n            // Find the target block and its connection point\r\n            const targetBlock = typeof connection.inputBlock === \"string\" ? blockNameMap.get(connection.inputBlock) : blockIdMap.get(connection.inputBlock);\r\n            if (!targetBlock) {\r\n                throw new Error(`Target block ${connection.inputBlock} not found`);\r\n            }\r\n\r\n            const targetConnectionPoint = targetBlock.inputs.find((input) => input.name === connection.inputConnectionPoint);\r\n            if (!targetConnectionPoint || typeof targetConnectionPoint !== \"object\") {\r\n                throw new Error(`Block ${connection.inputBlock} does not have a connection point named ${connection.inputConnectionPoint}`);\r\n            }\r\n\r","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/smartFilters/src/serialization/smartFilterDeserializer.ts#L77-L113","documentation":"When reconstructing connections, the deserializer looks up the connection's output (source) block by name or id in the maps built from the already-deserialized blocks. If no block matches connection.outputBlock, the serialized connection graph is dangling and deserialization fails. This validates referential integrity of the filter's connection list.","triggerScenarios":"A serialized connection references an outputBlock whose block failed to deserialize (removed after error 864 collection is bypassed — no, blocks that failed cause 864; here the block is simply absent from JSON), the name/id was renamed in the JSON, or connection entries were hand-edited or merged incorrectly.","commonSituations":"Hand-editing .smartfilter JSON, deleting a block in the editor while stale connections remain, older exports using ids that no longer match, concatenating filters incorrectly.","solutions":["Fix or remove the dangling connection entry in the serialized JSON so outputBlock matches an existing block's name or uniqueId.","Re-export the filter from the editor instead of hand-editing connection data.","Validate that every connection's outputBlock exists in serializedSmartFilter.blocks before deserializing.","Check for name-vs-id mismatch: strings resolve via blockNameMap, numbers via blockIdMap — ensure the field type matches how blocks were serialized.","If blocks failed to deserialize earlier (864), fix those registrations; the missing blocks cause downstream lookup failures."],"exampleFix":"// before\n{ \"outputBlock\": \"BlurOld\", \"outputConnectionPoint\": \"out\", ... } // no such block\n// after\n{ \"outputBlock\": \"Blur\", \"outputConnectionPoint\": \"out\", ... } // matches a deserialized block name","handlingStrategy":"validation","validationCode":"function validateSourceBlocks(serialized) {\n  const names = new Set(serialized.blocks.map((b) => b.name));\n  const ids = new Set(serialized.blocks.map((b) => b.uniqueId));\n  for (const c of serialized.connections) {\n    const ok = typeof c.outputBlock === \"string\" ? names.has(c.outputBlock) : ids.has(c.outputBlock);\n    if (!ok) throw new Error(`Connection references missing outputBlock: ${c.outputBlock}`);\n  }\n}","typeGuard":"function sourceBlockExists(conn, blocks) {\n  const map = new Map(blocks.flatMap((b) => [[b.name, b], [b.uniqueId, b]]));\n  return map.has(conn.outputBlock);\n}","tryCatchPattern":"try {\n  const filter = await SmartFilterDeserializer.DeserializeAsync(runtime, container, json);\n} catch (e) {\n  if (/Source block .+ not found/.test(e.message)) {\n    throw new Error(\"Filter JSON has a connection to a missing source block — repair or re-export the file\");\n  }\n  throw e;\n}","preventionTips":["Never hand-edit connection lists; re-export from the editor.","Delete blocks together with their connections.","Pre-validate all connection endpoints against the blocks array.","Keep name/id semantics: strings are names, numbers are uniqueIds.","Back up working filter files before manual edits."],"tags":["smart-filters","deserialization","graph-integrity","validation"],"backgroundTag":"dangling-reference-in-graph","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}