Skip to content

[-] fix serialization of errors in db logger#744

Merged
pashagolub merged 2 commits intocybertec-postgresql:masterfrom
MaxaiZer:fix-error-logging
Mar 9, 2026
Merged

[-] fix serialization of errors in db logger#744
pashagolub merged 2 commits intocybertec-postgresql:masterfrom
MaxaiZer:fix-error-logging

Conversation

@MaxaiZer
Copy link
Contributor

@MaxaiZer MaxaiZer commented Feb 11, 2026

Task errors are currently serialized inconsistently. If ExecuteSQLCommand fails during this block:

if len(paramValues) == 0 { 
  ct, e := executor.Exec(ctx, task.Command)
  pge.LogTaskExecution(context.Background(), task, errCodes[e != nil], ct.String(), "") 
  return e
}

message_data.error in the "Task execution failed" log entry (in the timetable.log table) will contain a full pgconn.PgError struct:

{"task": 1, "vxid": 1, "chain": 1, "error": {"Code": "42P02", "File": "parse_expr.c", "Hint": "", "Line": 901, "Where": "", "Detail": "", "Message": "there is no parameter $1", "Routine": "transformParamRef", "Position": 175, "Severity": "ERROR", "TableName": "", "ColumnName": "", "SchemaName": "", "DataTypeName": "", "InternalQuery": "", "ConstraintName": "", "InternalPosition": 0, "SeverityUnlocalized": "ERROR"}}

If it fails during parameter parsing:

if err = json.Unmarshal([]byte(val), &params); err != nil {
    return
}

message_data.error will contain struct with no actual error message:

{"task": 1, "vxid": 1, "chain": 1, "error": {"Type": {}, "Field": "", "Value": "string", "Offset": 9, "Struct": ""}}

And if ExecuteSQLCommand returns joined errors, message_data.error becomes empty:

{"task": 1, "vxid": 1, "chain": 1, "error": {}}

After fix examples:

  • single postgres error:
{"task": 1, "vxid": 1, "chain": 1, "error": "ERROR: there is no parameter $1 (SQLSTATE 42P02)"}
  • parameter parse error:
{"task": 1, "vxid": 1, "chain": 1, "error": "failed to parse parameter \"1 month\": json: cannot unmarshal string into Go value of type []interface {}"}
  • joined errors (task with two parameters: correct and incorrect):
{"task": 1, "vxid": 1, "chain": 1, "error": "ERROR: procedure F_CreatePartitions(date, date) does not exist (SQLSTATE 42883)\nfailed to parse parameter \"1 month\": json: cannot unmarshal string into Go value of type []interface {}"}

@pashagolub pashagolub self-assigned this Feb 13, 2026
@pashagolub pashagolub added the bug Something isn't working label Feb 13, 2026
@coveralls
Copy link

coveralls commented Feb 13, 2026

Pull Request Test Coverage Report for Build 22749875293

Details

  • 3 of 7 (42.86%) changed or added relevant lines in 2 files are covered.
  • 4 unchanged lines in 1 file lost coverage.
  • Overall coverage increased (+0.03%) to 87.273%

Changes Missing Coverage Covered Lines Changed/Added Lines %
internal/pgengine/log_hook.go 0 4 0.0%
Files with Coverage Reduction New Missed Lines %
internal/pgengine/log_hook.go 4 81.08%
Totals Coverage Status
Change from base Build 21996564729: 0.03%
Covered Lines: 1728
Relevant Lines: 1980

💛 - Coveralls

@pashagolub pashagolub requested a review from 0xgouda February 13, 2026 17:33
@0xgouda 0xgouda force-pushed the fix-error-logging branch from e23fc65 to ec3a479 Compare March 6, 2026 05:02
@0xgouda
Copy link

0xgouda commented Mar 6, 2026

@MaxaiZer I tried to reproduce the 3 cases you are describing using a pg_timetable instance built from master and I can't see them. I get all outputs for the Task execution failed message similar to your "After" section:

# no parameters, doesn't contain a pgconn.PgError struct
{"chain":39,"error":"ERROR: there is no parameter $1 (SQLSTATE 42P02)","level":"error","msg":"Task execution failed","task":39,"time":"2026-03-06T08:33:53+02:00","vxid":17179871472}

# 1 invalid parameter, doesn't contain struct with no actual error message
{"chain":11,"error":"json: cannot unmarshal string into Go value of type []interface {}","level":"error","msg":"Task execution failed","task":11,"time":"2026-03-06T08:12:29+02:00","vxid":17179870230}

# 2 parameters (1 correct and 1 incorrect), doesn't return empty error
{"chain":36,"error":"ERROR: invalid input syntax for type boolean: \"7\" (SQLSTATE 22P02)","level":"error","msg":"Task execution failed","task":36,"time":"2026-03-06T08:25:12+02:00","vxid":17179871259}

Am I missing something? can you add reproduction steps?


but I can still see the value of the below block that you added:

if parseErr := json.Unmarshal([]byte(val), &params); parseErr != nil {
	err = errors.Join(err, fmt.Errorf("failed to parse parameter %s: %w", val, parseErr))

@MaxaiZer MaxaiZer changed the title [-] fix JSON serialization of different error types in task execution logging [-] fix JSON serialization of different error types in task execution logging (DB) Mar 6, 2026
@MaxaiZer
Copy link
Contributor Author

MaxaiZer commented Mar 6, 2026

@0xgouda Oh, I should have clarified: this is related to db logging (timetable.log table)

Copy link

@0xgouda 0xgouda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for your contribution.

@0xgouda 0xgouda changed the title [-] fix JSON serialization of different error types in task execution logging (DB) [-] fix serialization of errors in db logger Mar 8, 2026
@0xgouda 0xgouda requested a review from pashagolub March 8, 2026 12:37
@pashagolub pashagolub merged commit 803a366 into cybertec-postgresql:master Mar 9, 2026
15 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants