{"record":{"id":"2b9b4294199a916e","repo":"bytebase/bytebase","slug":"failed-to-get-plan","errorCode":null,"errorMessage":"failed to get plan","messagePattern":"failed to get plan","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/runner/reviewrun/rule_executor.go","lineNumber":53,"sourceCode":"\t\tdbFactory:    dbFactory,\n\t}\n}\n\n// RunOnce implements Executor.\nfunc (e *RuleExecutor) RunOnce(ctx context.Context, projectID string, issueUID int64) error {\n\tissue, err := e.store.GetIssue(ctx, &store.FindIssueMessage{ProjectIDs: []string{projectID}, UID: &issueUID})\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to get issue\")\n\t}\n\tif issue == nil {\n\t\treturn errors.Errorf(\"issue %d not found in project %s\", issueUID, projectID)\n\t}\n\tif issue.PlanUID == nil {\n\t\treturn errors.Errorf(\"issue %d has no plan\", issueUID)\n\t}\n\tplan, err := e.store.GetPlan(ctx, &store.FindPlanMessage{ProjectID: projectID, UID: issue.PlanUID})\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to get plan\")\n\t}\n\tif plan == nil {\n\t\treturn errors.Errorf(\"plan %d not found in project %s\", *issue.PlanUID, projectID)\n\t}\n\tproject, err := e.store.GetProjectByResourceID(ctx, projectID)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to get project\")\n\t}\n\tif project == nil {\n\t\treturn errors.Errorf(\"project %s not found\", projectID)\n\t}\n\n\tdatabaseGroup, err := plancheck.GetDatabaseGroupForPlan(ctx, e.store, plan, nil)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to get database group for plan\")\n\t}\n\t// DeriveReviewTargets, not DeriveCheckTargets: review must evaluate every\n\t// (spec, target) unit, so the CI sampling limit does not apply.","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/runner/reviewrun/rule_executor.go#L35-L71","documentation":"RunOnce wraps a store error from GetPlan when fetching the issue's linked plan (FindPlanMessage{ProjectID, UID}). The wrap keeps the underlying metadata store failure with context 'failed to get plan'. A nil plan is handled separately ('plan not found'), so this always indicates a real store/query failure.","triggerScenarios":"e.store.GetPlan returns a non-nil error while the review-run scheduler resolves issue.PlanUID during RunOnce.","commonSituations":"Metadata DB connectivity loss during scheduler execution; context cancellation/timeouts under load; corrupted plans table causing query errors.","solutions":["Inspect the wrapped root cause and restore metadata DB connectivity or fix the underlying query error.","Rely on the scheduler's retry; transient store failures recover on subsequent ticks.","Check server logs and metadata Postgres health for the failing plan query."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if err := ctx.Err(); err != nil { return err }\n// ensure issue.PlanUID is non-nil before the GetPlan call","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"failed to get plan\") {\n    // log errors.Unwrap(err) for the store root cause; retry on next tick\n}","preventionTips":["Use bounded context timeouts with retry/backoff in the scheduler loop.","Distinguish wrapped store errors (retryable) from nil-plan results (permanent) in logs.","Monitor metadata Postgres health to catch query failures before they starve the scheduler."],"tags":["review-run","plan","store-error","wrapped-error"],"backgroundTag":"database-query-failed","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"}