{"record":{"id":"cacdb1a5a9c8ffe0","repo":"bytebase/bytebase","slug":"cannot-create-rollout-for-a-draft-issue-submit-it","errorCode":null,"errorMessage":"cannot create rollout for a draft issue; submit it first","messagePattern":"cannot create rollout for a draft issue; submit it first","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/api/v1/rollout_service.go","lineNumber":47,"sourceCode":"\t\"github.com/bytebase/bytebase/backend/plugin/db\"\n\tparserbase \"github.com/bytebase/bytebase/backend/plugin/parser/base\"\n\t\"github.com/bytebase/bytebase/backend/store\"\n\t\"github.com/bytebase/bytebase/backend/utils\"\n)\n\n// RolloutService represents a service for managing rollout.\ntype RolloutService struct {\n\tv1connect.UnimplementedRolloutServiceHandler\n\tstore          *store.Store\n\tdbFactory      *dbfactory.DBFactory\n\tbus            *bus.Bus\n\twebhookManager *webhook.Manager\n\tiamManager     *iam.Manager\n}\n\nvar (\n\terrStaleRolloutApproval   = errors.New(\"cannot create rollout because issue approval is stale\")\n\terrDraftIssueNotSubmitted = errors.New(\"cannot create rollout for a draft issue; submit it first\")\n)\n\n// IsStaleRolloutApprovalError reports whether rollout creation lost the approval-version race.\nfunc IsStaleRolloutApprovalError(err error) bool {\n\treturn errors.Is(err, errStaleRolloutApproval)\n}\n\n// IsDraftIssueNotSubmittedError reports whether rollout creation was blocked by a draft issue.\nfunc IsDraftIssueNotSubmittedError(err error) bool {\n\treturn errors.Is(err, errDraftIssueNotSubmitted)\n}\n\n// NewRolloutService returns a rollout service instance.\nfunc NewRolloutService(store *store.Store, dbFactory *dbfactory.DBFactory, bus *bus.Bus, webhookManager *webhook.Manager, iamManager *iam.Manager) *RolloutService {\n\treturn &RolloutService{\n\t\tstore:          store,\n\t\tdbFactory:      dbFactory,\n\t\tbus:            bus,","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/api/v1/rollout_service.go#L29-L65","documentation":"Rollout creation guard (errDraftIssueNotSubmitted): the plan's issue is still a draft, and rollouts can only be created for submitted issues. Failing here prevents a rollout executing a plan nobody has finalized; detected via IsDraftIssueNotSubmittedError.","triggerScenarios":"Calling CreateRollout (or CreateRolloutAndPendingTasks) with a plan whose issue has not been submitted — e.g. a persisted draft issue passed directly to rollout creation.","commonSituations":"Automation pipelines creating issues programmatically and immediately rolling out without the submit step; UI state drift where a user triggers rollout on a draft; retries against issues that were reverted to draft.","solutions":["Submit the issue first (via the issue service) and then call CreateRollout","Guard callers with IsDraftIssueNotSubmittedError and prompt the user to submit","Check the issue's state before attempting rollout creation"],"exampleFix":"// before\n_, err := rolloutClient.CreateRollout(ctx, req)\n// after\nif err := issueClient.SubmitIssue(ctx, issueReq); err != nil {\n\treturn err\n}\n_, err := rolloutClient.CreateRollout(ctx, req)","handlingStrategy":"try-catch","validationCode":"if issue.GetState() == v1pb.Issue_STATE_UNSPECIFIED /* or draft marker */ {\n\treturn errors.New(\"submit the issue before creating a rollout\")\n}","typeGuard":null,"tryCatchPattern":"_, err := rolloutClient.CreateRollout(ctx, req)\nif err != nil {\n\tif v1.IsDraftIssueNotSubmittedError(err) {\n\t\treturn fmt.Errorf(\"submit the issue first, then retry the rollout\")\n\t}\n\treturn err\n}","preventionTips":["Make issue submission a mandatory step in automation pipelines before rollout","Check issue state in the UI/API flow before exposing the rollout action"],"tags":["rollout","issue","workflow"],"backgroundTag":"invalid-state-transition","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}