{"record":{"id":"9346e0be9e692969","repo":"OpenBMB/ChatDev","slug":"node-config-block-required","errorCode":null,"errorMessage":"node config block required","messagePattern":"node config block required","errorType":"validation","errorClass":"ConfigError","httpStatus":null,"severity":"error","filePath":"entity/configs/node/node.py","lineNumber":198,"sourceCode":"\n        description = optional_str(mapping, \"description\", path)\n        # keep_context = bool(mapping.get(\"keep_context\", False))\n        log_output = bool(mapping.get(\"log_output\", True))\n        context_window = int(mapping.get(\"context_window\", 0))\n        input_value = ensure_list(mapping.get(\"input\"))\n        output_value = ensure_list(mapping.get(\"output\"))\n\n        input_messages: List[Message] = []\n        for value in input_value:\n            if isinstance(value, dict) and \"role\" in value:\n                input_messages.append(Message.from_dict(value))\n            elif isinstance(value, Message):\n                input_messages.append(value)\n            else:\n                input_messages.append(Message(role=MessageRole.USER, content=str(value)))\n\n        if \"config\" not in mapping or mapping[\"config\"] is None:\n            raise ConfigError(\"node config block required\", extend_path(path, \"config\"))\n        config_obj = schema.config_cls.from_dict(\n            mapping[\"config\"], path=extend_path(path, \"config\")\n        )\n\n        formatted_output: List[NodePayload] = []\n        for value in output_value:\n            if isinstance(value, dict) and \"role\" in value:\n                formatted_output.append(Message.from_dict(value))\n            elif isinstance(value, Message):\n                formatted_output.append(value)\n            else:\n                formatted_output.append(\n                    Message(role=MessageRole.ASSISTANT, content=str(value))\n                )\n\n        # Dynamic configuration parsing removed - dynamic is now on edges\n\n        node = cls(","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/entity/configs/node/node.py#L180-L216","documentation":"NodeConfig.from_dict requires a non-null 'config' key in the node mapping, since every node type needs its type-specific config payload. Missing or null 'config' raises this ConfigError with path '<node>.config'.","triggerScenarios":"Defining a node with id/type but no config block, or config: null, in a graph definition passed to from_dict (directly or via add_successor).","commonSituations":"Skeleton configs where the config block was left as a TODO; minimal test nodes; migrations or linters that strip 'empty' blocks.","solutions":["Add a config mapping appropriate to the node type, e.g. config: {} if no options are needed","Copy the config block from a working example for that node type","Pre-validate graph configs with a schema check before submission"],"exampleFix":"# before\n- id: n1\n  type: python_runner\n# after\n- id: n1\n  type: python_runner\n  config:\n    timeout_seconds: 60","handlingStrategy":"validation","validationCode":"for n in cfg.get('nodes', []):\n    if not isinstance(n.get('config'), dict):\n        n['config'] = {}  # or raise","typeGuard":null,"tryCatchPattern":"try:\n    NodeConfig.from_dict(data, path='nodes[0]')\nexcept ConfigError as e:\n    if 'node config block required' in str(e):\n        data['config'] = {}\n        NodeConfig.from_dict(data, path='nodes[0]')","preventionTips":["Template node configs with a default config: {} block","Lint for required keys per node type"],"tags":["config","node","missing-field"],"backgroundTag":"missing-required-config-field","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}