{"record":{"id":"227024f378204512","repo":"gastownhall/beads","slug":"metadata-validation-failed-for-issue-s-w","errorCode":null,"errorMessage":"metadata validation failed for issue %s: %w","messagePattern":"metadata validation failed for issue (.+?): %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/create.go","lineNumber":531,"sourceCode":"\t\t\taffectedIssues, affectedWisps, err = AffectedByDepChangeInTx(ctx, tx, dependency.source, dependency.target, dependency.depType)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"affected by created dependency %s -> %s: %w\", dependency.source, dependency.target, err)\n\t\t}\n\t\tfor _, id := range affectedIssues {\n\t\t\tadd(id, false)\n\t\t}\n\t\tfor _, id := range affectedWisps {\n\t\t\tadd(id, true)\n\t\t}\n\t}\n\treturn issueIDs, wispIDs, nil\n}\n\n// PrepareIssueForInsert normalizes timestamps, validates, and computes the content hash.\nfunc PrepareIssueForInsert(issue *types.Issue, customStatuses, customTypes []string) error {\n\tif err := ValidateMetadataIfConfigured(issue.Metadata); err != nil {\n\t\treturn fmt.Errorf(\"metadata validation failed for issue %s: %w\", issue.ID, err)\n\t}\n\n\t// Normalize timestamps to UTC, defaulting to now.\n\tnow := time.Now().UTC()\n\tif issue.CreatedAt.IsZero() {\n\t\tissue.CreatedAt = now\n\t} else {\n\t\tissue.CreatedAt = issue.CreatedAt.UTC()\n\t}\n\tif issue.UpdatedAt.IsZero() {\n\t\tissue.UpdatedAt = now\n\t} else {\n\t\tissue.UpdatedAt = issue.UpdatedAt.UTC()\n\t}\n\n\t// Ensure closed issues have a closed_at timestamp.\n\tif issue.Status == types.StatusClosed && issue.ClosedAt == nil {\n\t\tmaxTime := issue.CreatedAt","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/create.go#L513-L549","documentation":"PrepareIssueForInsert validates the issue's optional Metadata field against the configured metadata schema via ValidateMetadataIfConfigured before insert, wrapping failures as \"metadata validation failed for issue %s: %w\" with the issue ID. Metadata validation only runs when a schema is configured; unstructured metadata passes untouched when none is set.","triggerScenarios":"Creating/updating an issue (CreateIssueInTxWithResult, PromoteFromEphemeralInTx, PreparePublicCreateRequest) whose Metadata map violates the configured schema: missing required keys, wrong value types, or disallowed fields; importing issues from another repo whose metadata does not match local config.","commonSituations":"Teams adding a metadata schema to an existing database whose old issues (or import payloads) predate it; automation writing metadata keys with wrong JSON types (string vs number); typo'd metadata keys in scripts.","solutions":["Read the wrapped validation error to see which metadata key/rule failed and correct the issue's Metadata map before insert.","Run the same validation client-side (ValidateMetadataIfConfigured) before submitting so the failure surfaces at the call site.","If legacy issues legitimately lack new fields, relax the configured schema (make fields optional) or backfill the metadata."],"exampleFix":"// before\nissue := &types.Issue{Title: \"x\", Metadata: map[string]any{\"priority\": \"high\"}}\n// schema expects integer priority -> validation fails\n\n// after\nissue := &types.Issue{Title: \"x\", Metadata: map[string]any{\"priority\": 2}}\nif err := issueops.ValidateMetadataIfConfigured(issue.Metadata); err != nil {\n\treturn fmt.Errorf(\"fix metadata: %w\", err)\n}","handlingStrategy":"validation","validationCode":"if err := issueops.ValidateMetadataIfConfigured(issue.Metadata); err != nil {\n\treturn fmt.Errorf(\"metadata for %s invalid: %w\", issue.ID, err)\n}","typeGuard":null,"tryCatchPattern":"if err := store.CreateIssue(ctx, issue); err != nil {\n\tif strings.Contains(err.Error(), \"metadata validation failed\") {\n\t\treturn fmt.Errorf(\"reject/repair metadata before retry: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Share one metadata-building helper so keys and types are consistent everywhere.","When introducing a metadata schema, backfill or grandfather existing issues first.","Match JSON types exactly to the schema (int vs string) in automation that writes metadata."],"tags":["validation","metadata","schema"],"backgroundTag":"metadata-validation-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}