{"record":{"id":"567e1ffab98b0ebf","repo":"iflytek/astron-agent","slug":"when-mode-mode-tablename-is-required","errorCode":null,"errorMessage":"When mode={mode}, tableName is required.","messagePattern":"When mode=(.+?), tableName is required\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"core/workflow/engine/nodes/pgsql/pgsql_node.py","lineNumber":128,"sourceCode":"        if info.data.get(\"mode\") == 0 and (v is None or v.strip() == \"\"):\n            raise ValueError(\n                \"When mode=0 (CUSTOM), sql is required and must not be empty.\"\n            )\n        return v\n\n    @field_validator(\"tableName\", mode=\"after\")\n    def _check_table_name(cls, v: str | None, info: ValidationInfo) -> str | None:\n        \"\"\"\n        Check if the table name is valid for the given mode.\n\n        :param v: Table name string\n        :param info: ValidationInfo\n        :return: Table name string\n        :raises ValueError: If the table name is invalid\n        \"\"\"\n        mode = info.data.get(\"mode\")\n        if mode in (1, 2, 3, 4) and (v is None or v.strip() == \"\"):\n            raise ValueError(f\"When mode={mode}, tableName is required.\")\n        return v\n\n    @field_validator(\"cases\", mode=\"after\")\n    def _check_cases_for_update_delete(\n        cls, v: List[Case], info: ValidationInfo\n    ) -> List[Case]:\n        \"\"\"\n        Check if the cases are valid for the given mode.\n\n        :param v: Cases list\n        :param info: ValidationInfo\n        :return: Cases list\n        :raises ValueError: If the cases are invalid\n        \"\"\"\n        mode = info.data.get(\"mode\")\n        if mode in (2, 4) and not v:\n            raise ValueError(\n                \"When mode=2 (UPDATE) or mode=4 (DELETE), cases cannot be empty.\"","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/workflow/engine/nodes/pgsql/pgsql_node.py#L110-L146","documentation":"Pydantic field validator on the PGSQL node's `tableName` field. Modes 1-4 (INSERT/UPDATE/SELECT/DELETE) operate on a table, so `tableName` must be a non-empty string; otherwise model construction raises ValueError (pydantic ValidationError).","triggerScenarios":"Constructing PgsqlNodeData with mode in (1,2,3,4) and `tableName` set to None, empty, or whitespace-only.","commonSituations":"Workflow author picks a DML mode but forgets to select the target table; frontend sends a stale node config after table selection was cleared; template import missing tableName.","solutions":["Set a valid `tableName` in the node config when using any non-CUSTOM mode.","If no table applies, use mode=0 (CUSTOM) with explicit SQL instead.","Enforce table selection in the workflow editor UI before saving the node.","Surface the pydantic ValidationError per-field at import/debug time so the author immediately sees tableName is missing."],"exampleFix":"// before\nPgsqlNodeData(mode=2, tableName=\"\", cases=[...])\n// after\nPgsqlNodeData(mode=2, tableName=\"users\", cases=[...])","handlingStrategy":"validation","validationCode":"def validate_table_name(node_cfg: dict):\n    if node_cfg.get(\"mode\") in (1, 2, 3, 4) and not (node_cfg.get(\"tableName\") or \"\").strip():\n        raise ValueError(f\"mode={node_cfg['mode']} requires tableName\")","typeGuard":"def has_table_name(cfg) -> bool:\n    return cfg.mode == 0 or bool(cfg.tableName and cfg.tableName.strip())","tryCatchPattern":"try:\n    node_data = PgsqlNodeData(**cfg)\nexcept ValidationError as e:\n    if any(\"tableName is required\" in err[\"msg\"] for err in e.errors()):\n        show_field_error(\"tableName\", \"Select a target table\")\n    raise","preventionTips":["Make table selection a required form field for modes 1-4 in the editor","Validate node configs when saving/importing workflows","Clear or re-map tableName when the user switches modes"],"tags":["validation","pydantic","configuration","sql"],"backgroundTag":"schema-validation-failed","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}