{"record":{"id":"afd0271e6304bf84","repo":"apache/beam","slug":"unable-to-create-batch-read-only-transaction","errorCode":null,"errorMessage":"unable to create batch read only transaction: ","messagePattern":"unable to create batch read only transaction: ","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"sdks/go/pkg/beam/io/spannerio/generate_partitions.go","lineNumber":84,"sourceCode":"\tdb string,\n\tquery string,\n\toptions queryOptions,\n) *generatePartitionsFn {\n\tif db == \"\" {\n\t\tpanic(\"no database provided\")\n\t}\n\n\treturn &generatePartitionsFn{\n\t\tspannerFn: newSpannerFn(db),\n\t\tQuery:     query,\n\t\tOptions:   options,\n\t}\n}\n\nfunc (f *generatePartitionsFn) ProcessElement(ctx context.Context, _ []byte, emit func(partitionedRead)) error {\n\ttxn, err := f.client.BatchReadOnlyTransaction(ctx, f.Options.TimestampBound)\n\tif err != nil {\n\t\tpanic(\"unable to create batch read only transaction: \" + err.Error())\n\t}\n\tdefer txn.Close()\n\n\tmode := spannerpb.ExecuteSqlRequest_PROFILE\n\n\tpartitions, err := txn.PartitionQueryWithOptions(ctx, spanner.Statement{SQL: f.Query}, partitionOptions(f.Options), spanner.QueryOptions{Mode: &mode})\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"unable to partition query: %v\", err))\n\t}\n\n\tfor _, p := range partitions {\n\t\temit(newPartitionedRead(txn.ID, p))\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":66,"sourceCodeEnd":101,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/io/spannerio/generate_partitions.go#L66-L101","documentation":"During processing, generatePartitionsFn panics if it cannot create a Cloud Spanner batch read-only transaction. The error from the Spanner client is appended to the panic message. Unlike construction-time panics, this fires on workers while the pipeline is running, usually due to connectivity, credentials, or an invalid database path.","triggerScenarios":"f.client.BatchReadOnlyTransaction(ctx, f.Options.TimestampBound) returns an error — e.g. unreachable Spanner endpoint, missing/insufficient IAM permissions (spanner.backup/reader or db reader), bad TestEndpoint override, or invalid TimestampBound.","commonSituations":"Running Dataflow workers without access to the Spanner VPC/network; service account lacking spanner.databaseClient or viewer roles; typo'd instance/database path; stale or invalid credentials.","solutions":["Read the wrapped error in the panic message and fix the underlying Spanner client error.","Verify the database path and that the pipeline's service account has Spanner read permissions.","Check network connectivity (VPC, firewall, TestEndpoint override) from workers.","Confirm the TimestampBound options are valid (e.g. a readable timestamp not in the future)."],"exampleFix":"// before\nspannerio.Read with TestEndpoint pointing at a dead emulator\n// after\nuse a reachable emulator endpoint and export SPANNER_EMULATOR_HOST, or remove the override for production","handlingStrategy":"try-catch","validationCode":"// pre-flight: open a plain client and ping\nclient, err := spanner.NewClient(ctx, db)\nif err != nil {\n    return fmt.Errorf(\"spanner unreachable: %w\", err)\n}\nclient.Close()","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        if s, ok := r.(string); ok && strings.Contains(s, \"unable to create batch read only transaction\") {\n            // log s, alert, retry pipeline with backoff\n        } else { panic(r) }\n    }\n}()","preventionTips":["Verify worker network access to Spanner (VPC/firewall, no dead TestEndpoint).","Grant the pipeline service account Spanner read roles.","Validate TimestampBound settings (not in the future, stale reads bounded)."],"tags":["go","apache-beam","spanner","panic","database","gcp"],"backgroundTag":"database-query-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}