{"record":{"id":"8c2ac1178d9e6d7d","repo":"apache/beam","slug":"could-not-apply-mutation-v","errorCode":null,"errorMessage":"could not apply mutation: %v","messagePattern":"could not apply mutation: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/io/bigtableio/bigtable.go","lineNumber":273,"sourceCode":"\t}\n\n\treturn nil\n}\n\nfunc validateMutation(mutation Mutation) error {\n\tif len(mutation.Ops) > 100000 {\n\t\treturn fmt.Errorf(\"one instance of bigtableio.Mutation must not have more than 100,000 operations/mutations, see https://cloud.google.com/bigtable/docs/writes#batch\")\n\t}\n\treturn nil\n}\n\nfunc tryApplyBulk(errs []error, processErr error) error {\n\tif processErr != nil {\n\t\treturn fmt.Errorf(\"bulk apply procces failed: %v\", processErr)\n\t}\n\tfor _, err := range errs {\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not apply mutation: %v\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc getBigtableMutation(mutation Mutation) *bigtable.Mutation {\n\tbigtableMutation := bigtable.NewMutation()\n\tfor _, m := range mutation.Ops {\n\t\tbigtableMutation.Set(m.Family, m.Column, m.Ts, m.Value)\n\t}\n\treturn bigtableMutation\n}\n","sourceCodeStart":255,"sourceCodeEnd":286,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/io/bigtableio/bigtable.go#L255-L286","documentation":"After ApplyBulk returns, tryApplyBulk scans the per-row error slice it returns. The first non-nil entry is wrapped as 'could not apply mutation: %v'. This means the bulk RPC completed but specific individual mutations were rejected by Bigtable.","triggerScenarios":"ApplyBulk returns a non-nil error for at least one row index (bigtable.go:273); tryApplyBulk returns on the first such error. Causes: invalid row key, mutation too large, permission denied for that table, or entry-level server rejection.","commonSituations":"A few malformed row keys among millions of valid rows (empty keys, oversized keys); IAM revoked mid-job; per-cell limit violations (e.g. cell bigger than limits).","solutions":["Match the wrapped error back to the row key by index in the rowKeysInBatch slice and inspect that Mutation","Validate row keys and op sizes locally (non-empty, within limits) before enqueueing into the batch","Log and skip/retry only the failing rows instead of failing the whole bundle","Check IAM on the specific table if rejections are permission-related"],"exampleFix":"// before: fail on first error\nfor _, err := range errs {\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not apply mutation: %v\", err)\n\t}\n}\n// after: collect all failing indices for diagnosis\nfor i, err := range errs {\n\tif err != nil {\n\t\tlog.Errorf(ctx, \"row %d key=%q failed: %v\", i, rowKeysInBatch[i], err)\n\t}\n}","handlingStrategy":"validation","validationCode":"for i, m := range mutations {\n\tif rowKeysInBatch[i] == \"\" {\n\t\treturn fmt.Errorf(\"empty row key at batch index %d\", i)\n\t}\n}","typeGuard":null,"tryCatchPattern":"for i, err := range errs {\n\tif err != nil {\n\t\tlog.Errorf(ctx, \"bulk row %d key=%q rejected: %v\", i, rowKeysInBatch[i], err)\n\t\tfailed = append(failed, i)\n\t}\n}","preventionTips":["Sanitize row keys before batching (non-empty, valid, size-limited)","Correlate per-row errors back to keys by index for diagnosis","Handle rejected rows (log/quarantine/retry) instead of failing the whole bundle"],"tags":["gcp","bigtable","bulk-write","row-error","beam-io"],"backgroundTag":"database-write-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}