{"record":{"id":"efca44090664b563","repo":"gastownhall/beads","slug":"resolve-custom-issue-types-w","errorCode":null,"errorMessage":"resolve custom issue types: %w","messagePattern":"resolve custom issue types: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/aggregate.go","lineNumber":123,"sourceCode":"\t}\n\treturn nil\n}\n\n// ValidateScalarUpdates checks typed scalar values before they reach SQL.\nfunc ValidateScalarUpdates(ctx context.Context, tx DBTX, updates map[string]interface{}) error {\n\tif rawType, ok := updates[\"issue_type\"]; ok {\n\t\tvar issueType types.IssueType\n\t\tswitch value := rawType.(type) {\n\t\tcase types.IssueType:\n\t\t\tissueType = value\n\t\tcase string:\n\t\t\tissueType = types.IssueType(value)\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"%w: invalid issue type %v\", storage.ErrValidation, rawType)\n\t\t}\n\t\tcustomTypes, err := ResolveCustomTypesInTx(ctx, tx)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"resolve custom issue types: %w\", err)\n\t\t}\n\t\tif !issueType.IsValidWithCustom(customTypes) {\n\t\t\treturn fmt.Errorf(\"%w: invalid issue type %s\", storage.ErrValidation, issueType)\n\t\t}\n\t}\n\tfor _, field := range []string{\"assignee\", \"owner\"} {\n\t\tif raw, ok := updates[field]; ok {\n\t\t\tif value, ok := raw.(string); ok {\n\t\t\t\tif err := types.CheckFieldLen(field, value); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// AuthorizeAssigneeTransferWithPools is the assignee-transfer fence itself,","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/aggregate.go#L105-L141","documentation":"This error wraps a failure from ResolveCustomTypesInTx while ValidateScalarUpdates resolves the custom issue-type list needed to validate the requested type. It is not a validation verdict on the value itself; it signals the DB lookup for custom types failed, and the underlying cause is preserved in the chain.","triggerScenarios":"ValidateScalarUpdates (via updateIssueInTx) requests a 'type' update and ResolveCustomTypesInTx errors — e.g. transaction already aborted/rolled back, table missing, connection dropped, or SQL error reading custom type configuration.","commonSituations":"A prior statement in the same transaction failed, poisoning subsequent queries; schema migrations removed/renamed the custom types table; network or driver errors mid-transaction.","solutions":["Check the wrapped inner error for the root DB failure and fix that first","Ensure earlier statements in the transaction succeeded before attempting the type update; rollback and retry the whole transaction on failure","Verify the schema still contains the custom-types table after migrations"],"exampleFix":"// before\n// ignoring error from previous statement in same tx, then updating type\n// after\nif err := ensureTxHealthy(tx); err != nil { return err } // rollback on failure\nif err := issueops.ValidateScalarUpdates(ctx, tx, updates); err != nil {\n  tx.Rollback()\n  return err\n}","handlingStrategy":"try-catch","validationCode":"// No pre-call validation possible: failure is environmental (tx/DB state).\n// Guard instead by checking tx health before validation:\nif err := tx.PingContext(ctx); err != nil { return fmt.Errorf(\"tx unhealthy: %w\", err) }","typeGuard":null,"tryCatchPattern":"err := issueops.ValidateScalarUpdates(ctx, tx, updates)\nif err != nil && !errors.Is(err, storage.ErrValidation) {\n  // wrapped 'resolve custom issue types' failure: rollback and retry transaction\n  tx.Rollback()\n  return retryWithFreshTx(ctx, updates)\n}","preventionTips":["Roll back transactions immediately after any statement error instead of continuing","Keep custom-types tables intact in migrations; verify in schema tests","Retry the whole transaction (not just the statement) on transient DB errors"],"tags":["go","database","transaction","custom-types","storage"],"backgroundTag":"database-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}