apache/beam · critical

database not provided!

Error message

database not provided!

What it means

spannerio's internal spannerFn constructor panics when the Cloud Spanner database string is empty. Every read/write function in the package builds on spannerFn, so an empty database path makes the pipeline impossible to configure. It is treated as a programmer error rather than a runtime failure.

Source

Thrown at sdks/go/pkg/beam/io/spannerio/common.go:39

	"context"
	"fmt"

	"cloud.google.com/go/spanner"
	"google.golang.org/api/option"
	"google.golang.org/api/option/internaloption"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

type spannerFn struct {
	Database     string          `json:"database"` // Database is the spanner connection string
	TestEndpoint string          // Optional endpoint override for local testing. Not required for production pipelines.
	client       *spanner.Client // Spanner Client
}

func newSpannerFn(db string) spannerFn {
	if db == "" {
		panic("database not provided!")
	}

	return spannerFn{
		Database: db,
	}
}

func (f *spannerFn) Setup(ctx context.Context) error {
	if f.client == nil {
		var opts []option.ClientOption

		// Append emulator options assuming endpoint is local (for testing).
		if f.TestEndpoint != "" {
			opts = []option.ClientOption{
				option.WithEndpoint(f.TestEndpoint),
				option.WithGRPCDialOption(grpc.WithTransportCredentials(insecure.NewCredentials())),
				option.WithoutAuthentication(),
				internaloption.SkipDialSettingsValidation(),

View on GitHub (pinned to 12126d8942)

Solutions

  1. Pass the full database path: projects/<proj>/instances/<inst>/databases/<db>.
  2. Validate the db string is non-empty before calling spannerio.Read/Query/Write.
  3. Check the config source (env var, flag) that supplies the database id.

Example fix

// before
spannerio.Read(s, cfg.DB, table, reflect.TypeOf(Row{})) // cfg.DB == ""
// after
if cfg.DB == "" {
    return errors.New("spanner database is required")
}
spannerio.Read(s, cfg.DB, table, reflect.TypeOf(Row{}))
Defensive patterns

Strategy: validation

Validate before calling

if db == "" {
    return errors.New("spanner database path is required")
}
if !strings.HasPrefix(db, "projects/") {
    return fmt.Errorf("expected fully qualified database path, got %q", db)
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        if s, ok := r.(string); ok && s == "database not provided!" {
            // handle
        } else { panic(r) }
    }
}()

Prevention

When it happens

Trigger: Calling newSpannerFn("") indirectly via spannerio.Read/Query/Write (or newGeneratePartitionsFn/newQueryFn/newReadBatchFn/newWriteFn) with db == "".

Common situations: A config file or environment variable for the database is missing/empty; a flag default of "" never overridden; trimming a path like 'projects/p/instances/i/databases/d' incorrectly.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/a1d3c868fb83942b. Report an issue: GitHub.