{"record":{"id":"ed00892e6655d981","repo":"temporalio/temporal","slug":"unable-to-upsert-custom-search-attributes-w","errorCode":null,"errorMessage":"unable to upsert custom search attributes: %w","messagePattern":"unable to upsert custom search attributes: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/persistence/sql/sqlplugin/mysql/visibility.go","lineNumber":162,"sourceCode":"\ttx, err := db.BeginTxx(ctx, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer func() {\n\t\terr := tx.Rollback()\n\t\t// If the error is sql.ErrTxDone, it means the transaction already closed, so ignore error.\n\t\tif err != nil && !errors.Is(err, sql.ErrTxDone) {\n\t\t\t// Transaction rollback error should never happen, unless db connection was lost.\n\t\t\tretError = fmt.Errorf(\"transaction rollback failed: %w\", retError)\n\t\t}\n\t}()\n\tresult, err = tx.NamedExecContext(ctx, templateUpsertWorkflowExecution, finalRow)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to upsert workflow execution: %w\", err)\n\t}\n\t_, err = tx.NamedExecContext(ctx, templateUpsertCustomSearchAttributes, finalRow)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to upsert custom search attributes: %w\", err)\n\t}\n\t_, err = tx.NamedExecContext(ctx, templateUpsertChasmSearchAttributes, finalRow)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to upsert chasm search attributes: %w\", err)\n\t}\n\terr = tx.Commit()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn result, nil\n}\n\n// DeleteFromVisibility deletes a row from visibility table if it exist\nfunc (mdb *db) DeleteFromVisibility(\n\tctx context.Context,\n\tfilter sqlplugin.VisibilityDeleteFilter,\n) (result sql.Result, retError error) {\n\tdefer func() {","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/persistence/sql/sqlplugin/mysql/visibility.go#L144-L180","documentation":"The second statement in the ReplaceIntoVisibility transaction — the upsert into the custom search attributes table — failed, aborting the transaction. The error is wrapped as 'unable to upsert custom search attributes'. Common causes are custom search attribute constraint violations or stale schema on that table.","triggerScenarios":"ReplaceIntoVisibility: templateUpsertCustomSearchAttributes NamedExecContext fails — SA row violates key constraints, attribute data too long, missing columns from an unmigrated schema, or connection failure.","commonSituations":"Emitting custom search attributes not defined/allowed for the SQL visibility store; schema migration skipped during upgrade; very large memo/attribute values exceeding column sizes.","solutions":["Inspect the wrapped MySQL error for the precise constraint or truncation issue.","Migrate the visibility schema so custom_search_attributes tables match the release.","Validate custom search attribute keys/values against size and type limits.","Align registered custom search attribute definitions with those set on workflows.","Check DB connection health if the wrapped error is connection-level."],"exampleFix":"// before: oversized custom SA value\nsa := map[string]interface{}{\"CustomKeywordField\": strings.Repeat(\"x\", 1000)}\n\n// after: keep keyword fields within the column limit (e.g. <= 64 chars)\nsa := map[string]interface{}{\"CustomKeywordField\": \"x\"}","handlingStrategy":"validation","validationCode":"// Go: validate SA value sizes before the upsert path\nfor k, v := range row.SearchAttributes {\n    if b, err := json.Marshal(v); err != nil || len(b) > maxSABlobSize {\n        return fmt.Errorf(\"search attribute %q exceeds size limit\", k)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := db.ReplaceIntoVisibility(ctx, row); err != nil {\n    if strings.Contains(err.Error(), \"unable to upsert custom search attributes\") {\n        logger.Error(\"custom SA upsert failed; check SA limits and schema\", tag.Error(err))\n        return convertPersistenceErr(err)\n    }\n    return err\n}","preventionTips":["Enforce search attribute key/value limits at the application boundary.","Keep visibility schema migrated to the version matching the server.","Ensure registered custom SA definitions match those used by workflows."],"tags":["mysql","visibility","search-attributes","upsert"],"backgroundTag":"sql-upsert-failed","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}