{"record":{"id":"ffdd1d2bcc3bfaeb","repo":"apache/beam","slug":"no-database-provided-read","errorCode":null,"errorMessage":"no database provided!","messagePattern":"no database provided!","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"sdks/go/pkg/beam/io/spannerio/read.go","lineNumber":47,"sourceCode":"\t\"google.golang.org/api/iterator\"\n)\n\n// spannerTag is the struct tag key used to identify Spanner field names.\nconst (\n\tspannerTag = \"spanner\"\n)\n\nfunc init() {\n\tregister.DoFn3x1[context.Context, []byte, func(beam.X), error]((*queryFn)(nil))\n\tregister.Emitter1[beam.X]()\n}\n\n// Read reads all rows from the given spanner table. It returns a PCollection<t> for a given type T.\n// T must be a struct with exported fields that have the \"spanner\" tag. If the\n// table has more rows than t, then Read is implicitly a projection.\nfunc Read(s beam.Scope, db string, table string, t reflect.Type) beam.PCollection {\n\tif db == \"\" {\n\t\tpanic(\"no database provided!\")\n\t}\n\n\tcols := strings.Join(structx.InferFieldNames(t, spannerTag), \",\")\n\n\treturn query(s, db, fmt.Sprintf(\"SELECT %v from %v\", cols, table), t, newQueryOptions())\n}\n\n// Query executes a spanner query. It returns a PCollection<t> for a given type T. T must be a struct with exported\n// fields that have the \"spanner\" tag. By default, the transform uses spanners partitioned read ability to split\n// the results into bundles.\n// If the underlying query is not root-partitionable you can disable batching via UseBatching.\nfunc Query(s beam.Scope, db string, q string, t reflect.Type, options ...QueryOptionFn) beam.PCollection {\n\tqueryOptions := newQueryOptions(options...)\n\n\tif db == \"\" {\n\t\tpanic(\"no database provided!\")\n\t}\n","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/io/spannerio/read.go#L29-L65","documentation":"spannerio.Read panics when the database argument is an empty string. A table read always needs a fully qualified Cloud Spanner database path, and a missing one is treated as an immediate construction-time error before any query is built.","triggerScenarios":"Calling spannerio.Read(s, \"\", table, t) — typically when the db comes from a flag/env/config that was never set.","commonSituations":"Unset SPANNER_DATABASE env var; empty flag default; config file missing the database key; code refactor dropping the parameter.","solutions":["Pass the full path projects/<proj>/instances/<inst>/databases/<db>.","Validate db != \"\" before calling spannerio.Read and fail with a clear error.","Check the flag/env/config source that supplies the database identifier."],"exampleFix":"// before\nspannerio.Read(s, os.Getenv(\"DB\"), \"users\", reflect.TypeOf(User{})) // env unset\n// after\ndb := os.Getenv(\"DB\")\nif db == \"\" {\n    log.Fatal(\"spanner database must be set (projects/p/instances/i/databases/d)\")\n}\nspannerio.Read(s, db, \"users\", reflect.TypeOf(User{}))","handlingStrategy":"validation","validationCode":"if db == \"\" {\n    return errors.New(\"spanner database path is required for spannerio.Read\")\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        if s, ok := r.(string); ok && s == \"no database provided!\" {\n            // handle\n        } else { panic(r) }\n    }\n}()","preventionTips":["Check env vars/flags for the database at pipeline startup.","Use a single validated config struct for the Spanner coordinates.","Reject empty database strings at flag-parse time with a clear message."],"tags":["go","apache-beam","spanner","panic","missing-argument"],"backgroundTag":"missing-required-argument","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"}