{"record":{"id":"41b40b41c5c5ca3b","repo":"bytebase/bytebase","slug":"plan-has-no-specs","errorCode":null,"errorMessage":"plan has no specs","messagePattern":"plan has no specs","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/runner/taskrun/database_create_executor.go","lineNumber":72,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif !common.EngineSupportCreateDatabase(instance.Metadata.GetEngine()) {\n\t\treturn nil, errors.Errorf(\"creating database is not supported for engine %v\", instance.Metadata.GetEngine().String())\n\t}\n\n\tplan, err := exec.store.GetPlan(ctx, &store.FindPlanMessage{ProjectID: task.ProjectID, UID: &task.PlanID})\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to get plan %v\", task.PlanID)\n\t}\n\tif plan == nil {\n\t\treturn nil, errors.Errorf(\"plan %v not found\", task.PlanID)\n\t}\n\n\t// For create database plans, there is always exactly one spec\n\tif len(plan.Config.Specs) == 0 {\n\t\treturn nil, errors.Errorf(\"plan has no specs\")\n\t}\n\tcreateConfig := plan.Config.Specs[0].GetCreateDatabaseConfig()\n\tif createConfig == nil {\n\t\treturn nil, errors.Errorf(\"spec does not contain create database config\")\n\t}\n\n\t// Create database.\n\tslog.DebugContext(ctx, \"Start creating database...\",\n\t\tslog.String(\"instance\", instance.Metadata.GetTitle()),\n\t\tslog.String(\"database\", createConfig.Database),\n\t\tslog.String(\"statement\", statement),\n\t)\n\n\tvar environmentID *string\n\tif createConfig.Environment != \"\" {\n\t\tenvID, err := common.GetEnvironmentID(createConfig.Environment)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"failed to parse environment %s\", createConfig.Environment)","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/runner/taskrun/database_create_executor.go#L54-L90","documentation":"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].","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the plan record for the task's PlanID (project + UID) and confirm Config.Specs content in the metadata DB","Re-create the database-change pipeline so a fresh plan with a single create-database spec is generated, then re-run the task","If the plan was modified externally, restore the spec or re-submit the create-database change through the normal Bytebase UI/API","If it reproduces, report as a bug: plan creation should never persist a create-database plan with zero specs"],"exampleFix":"// before\nplan, err := exec.store.GetPlan(ctx, &store.FindPlanMessage{ProjectID: task.ProjectID, UID: &task.PlanID})\n// task submitted against a plan with empty specs -> \"plan has no specs\"\n\n// after\n// re-create the change so the plan is regenerated with its create-database spec,\n// or validate before creating the task:\nif len(plan.Config.Specs) == 0 {\n    return fmt.Errorf(\"plan %d has no specs; re-create the change\", task.PlanID)\n}","handlingStrategy":"validation","validationCode":"plan, err := store.GetPlan(ctx, &store.FindPlanMessage{ProjectID: task.ProjectID, UID: &task.PlanID})\nif err != nil || plan == nil || len(plan.Config.Specs) == 0 {\n    return fmt.Errorf(\"plan %d missing or has no specs; re-create the change\", task.PlanID)\n}","typeGuard":"if plan == nil || len(plan.Config.Specs) == 0 { return false }","tryCatchPattern":null,"preventionTips":["Never mutate or strip plan specs via direct API/DB access","Create tasks only through flows that generate plan + spec together","After metadata restores or migrations, verify plans still have their specs before resuming runs"],"tags":["task-run","plan","invariant","database-create"],"backgroundTag":"internal-invariant-violation","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}