bytebase/bytebase · error

plan has no specs

Error message

plan has no specs

What it means

DatabaseCreateExecutor.RunOnce loaded the plan for a create-database task and found plan.Config.Specs empty. Create-database plans must always carry exactly one spec holding the CreateDatabaseConfig; an empty spec list is an invariant violation, so the task run fails fast instead of dereferencing Specs[0].

Source

Thrown at backend/runner/taskrun/database_create_executor.go:72

	if err != nil {
		return nil, err
	}

	if !common.EngineSupportCreateDatabase(instance.Metadata.GetEngine()) {
		return nil, errors.Errorf("creating database is not supported for engine %v", instance.Metadata.GetEngine().String())
	}

	plan, err := exec.store.GetPlan(ctx, &store.FindPlanMessage{ProjectID: task.ProjectID, UID: &task.PlanID})
	if err != nil {
		return nil, errors.Wrapf(err, "failed to get plan %v", task.PlanID)
	}
	if plan == nil {
		return nil, errors.Errorf("plan %v not found", task.PlanID)
	}

	// For create database plans, there is always exactly one spec
	if len(plan.Config.Specs) == 0 {
		return nil, errors.Errorf("plan has no specs")
	}
	createConfig := plan.Config.Specs[0].GetCreateDatabaseConfig()
	if createConfig == nil {
		return nil, errors.Errorf("spec does not contain create database config")
	}

	// Create database.
	slog.DebugContext(ctx, "Start creating database...",
		slog.String("instance", instance.Metadata.GetTitle()),
		slog.String("database", createConfig.Database),
		slog.String("statement", statement),
	)

	var environmentID *string
	if createConfig.Environment != "" {
		envID, err := common.GetEnvironmentID(createConfig.Environment)
		if err != nil {
			return nil, errors.Wrapf(err, "failed to parse environment %s", createConfig.Environment)

View on GitHub (pinned to 1870550677)

Solutions

  1. Check the plan record for the task's PlanID (project + UID) and confirm Config.Specs content in the metadata DB
  2. Re-create the database-change pipeline so a fresh plan with a single create-database spec is generated, then re-run the task
  3. If the plan was modified externally, restore the spec or re-submit the create-database change through the normal Bytebase UI/API
  4. If it reproduces, report as a bug: plan creation should never persist a create-database plan with zero specs

Example fix

// before
plan, err := exec.store.GetPlan(ctx, &store.FindPlanMessage{ProjectID: task.ProjectID, UID: &task.PlanID})
// task submitted against a plan with empty specs -> "plan has no specs"

// after
// re-create the change so the plan is regenerated with its create-database spec,
// or validate before creating the task:
if len(plan.Config.Specs) == 0 {
    return fmt.Errorf("plan %d has no specs; re-create the change", task.PlanID)
}
Defensive patterns

Strategy: validation

Validate before calling

plan, err := store.GetPlan(ctx, &store.FindPlanMessage{ProjectID: task.ProjectID, UID: &task.PlanID})
if err != nil || plan == nil || len(plan.Config.Specs) == 0 {
    return fmt.Errorf("plan %d missing or has no specs; re-create the change", task.PlanID)
}

Type guard

if plan == nil || len(plan.Config.Specs) == 0 { return false }

Prevention

When it happens

Trigger: A task of type database create points at a plan whose Config.Specs array is empty — e.g. the plan was created/updated without any spec, specs were stripped by an import/export or API call, or the plan was written by an older/buggy code path that didn't attach the spec.

Common situations: Plan edited or re-created via API/automation that dropped the specs; plan data corrupted by a failed migration or manual DB edit; running an old task against a plan that was since replaced with an empty one.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06). Data as JSON: /api/errors/41b40b41c5c5ca3b. Report an issue: GitHub.