iflytek/astron-agent · error · CustomException
PG_SQL_NODE_EXECUTION_ERROR
PG_SQL_NODE_EXECUTION_ERROR
Error message
Database DML statement generation failed: {err} What it means
Catch-all wrapper in `generate_dml`: any exception during SQL generation/validation/compilation (SQLAlchemy compile errors, bad identifiers, template/variable resolution failures, plus the PG_SQL_PARAM_ERROR sub-cases) is re-raised as PG_SQL_NODE_EXECUTION_ERROR with the original message embedded.
Solutions
- Read the inner `{err}` text to find which statement failed and why.
- Print/inspect the compiled SQL by running generate_dml locally with the same node config.
- Validate table/column identifiers and case value types (str/int/float/bool only) in the node config.
- If the inner error is 'WHERE condition is empty', fix the cases as in errors 1326/1327; if it's a compile error, fix the SQL/identifiers.
Example fix
// before
cases=[Case(column="created_at", operator=">", value={"nested": "dict"})] # cannot literal-bind
// after
cases=[Case(column="created_at", operator=">", value="2024-01-01 00:00:00")] Defensive patterns
Strategy: try-catch
Validate before calling
# pre-validate identifiers and bindable types
def check_dml_inputs(cfg) -> str | None:
if cfg.tableName and not cfg.tableName.replace("_", "").isalnum():
return f"Invalid table name: {cfg.tableName}"
for c in getattr(cfg, "cases", []) or []:
if not isinstance(c.value, (str, int, float, bool)):
return f"Non-bindable case value type: {type(c.value)}"
return None Try / catch
try:
sql = await node.generate_dml(span)
except CustomException as e:
log.error("DML generation failed", detail=str(e)) # inner err names the real cause
raise Prevention
- Keep case values limited to str/int/float/bool so SQLAlchemy can literal-bind
- Use quoted-safe, conventional identifiers for tables and columns
- Dry-run SQL generation in the node debugger before publishing the workflow
When it happens
Trigger: Calling `generate_dml` (via `generate_config`) when SQLAlchemy's `text(...).bindparams(...).compile(...)` fails — invalid table/column identifiers, type-unresolvable literal binds, malformed mode/case data, or an unknown DBMode.
Common situations: Table or column names contain characters needing quoting; case values are of types SQLAlchemy cannot literal-bind (dict, bytes); mode enum mismatch after config schema changes; custom SQL with bad placeholders.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- Column names must be used in UPDATE SET clause
- PG_SQL_PARAM_ERROR
- SQLParseError
- 8516
- Error creating table
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/4a79e3266aaac568.
Report an issue: GitHub.
Appendix: source
Thrown at core/workflow/engine/nodes/pgsql/pgsql_node.py:491
),
}.get(
self.mode,
lambda: (_ for _ in ()).throw( # Throw exception for invalid mode
CustomException(
err_code=CodeEnum.PG_SQL_PARAM_ERROR,
err_msg="Mode is out of range",
cause_error="Mode is out of range",
)
),
)()
# Log generated SQL for tracing
await request_span.add_info_events_async({"sql_string": compiled_sql})
return compiled_sql
except Exception as e:
# Handle any errors during SQL generation
err = str(e)
request_span.add_error_event(err)
raise CustomException(
err_code=CodeEnum.PG_SQL_NODE_EXECUTION_ERROR,
err_msg=f"Database DML statement generation failed: {err}",
cause_error=f"Database DML statement generation failed: {err}",
) from e
async def generate_config(
self,
inputs: dict,
is_release: bool,
span: Span,
) -> PGSqlConfig:
"""Generate PostgreSQL configuration for database operations.
:param inputs: Input data dictionary containing variable values
:param is_release: Whether this is a production release
:param span: Tracing span for monitoring
:return: Configured PGSqlConfig object
:raises CustomException: If required parameters are missingView on GitHub (pinned to 5e758547a8)