gastownhall/beads · error

resolve custom issue types: %w

Error message

resolve custom issue types: %w

What it means

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.

Source

Thrown at internal/storage/issueops/aggregate.go:123

	}
	return nil
}

// ValidateScalarUpdates checks typed scalar values before they reach SQL.
func ValidateScalarUpdates(ctx context.Context, tx DBTX, updates map[string]interface{}) error {
	if rawType, ok := updates["issue_type"]; ok {
		var issueType types.IssueType
		switch value := rawType.(type) {
		case types.IssueType:
			issueType = value
		case string:
			issueType = types.IssueType(value)
		default:
			return fmt.Errorf("%w: invalid issue type %v", storage.ErrValidation, rawType)
		}
		customTypes, err := ResolveCustomTypesInTx(ctx, tx)
		if err != nil {
			return fmt.Errorf("resolve custom issue types: %w", err)
		}
		if !issueType.IsValidWithCustom(customTypes) {
			return fmt.Errorf("%w: invalid issue type %s", storage.ErrValidation, issueType)
		}
	}
	for _, field := range []string{"assignee", "owner"} {
		if raw, ok := updates[field]; ok {
			if value, ok := raw.(string); ok {
				if err := types.CheckFieldLen(field, value); err != nil {
					return err
				}
			}
		}
	}
	return nil
}

// AuthorizeAssigneeTransferWithPools is the assignee-transfer fence itself,

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped inner error for the root DB failure and fix that first
  2. Ensure earlier statements in the transaction succeeded before attempting the type update; rollback and retry the whole transaction on failure
  3. Verify the schema still contains the custom-types table after migrations

Example fix

// before
// ignoring error from previous statement in same tx, then updating type
// after
if err := ensureTxHealthy(tx); err != nil { return err } // rollback on failure
if err := issueops.ValidateScalarUpdates(ctx, tx, updates); err != nil {
  tx.Rollback()
  return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

// No pre-call validation possible: failure is environmental (tx/DB state).
// Guard instead by checking tx health before validation:
if err := tx.PingContext(ctx); err != nil { return fmt.Errorf("tx unhealthy: %w", err) }

Try / catch

err := issueops.ValidateScalarUpdates(ctx, tx, updates)
if err != nil && !errors.Is(err, storage.ErrValidation) {
  // wrapped 'resolve custom issue types' failure: rollback and retry transaction
  tx.Rollback()
  return retryWithFreshTx(ctx, updates)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/efca44090664b563. Report an issue: GitHub.