{"record":{"id":"ea822c20207a3628","repo":"wavetermdev/waveterm","slug":"error-getting-block-w-ea822c","errorCode":null,"errorMessage":"error getting block: %w","messagePattern":"error getting block: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/blockcontroller/durableshellcontroller.go","lineNumber":142,"sourceCode":"\t\t\twaveobj.MakeORef(waveobj.OType_Block, dsc.BlockId).String(),\n\t\t},\n\t\tData: rtStatus,\n\t})\n}\n\n// Start initializes or reconnects to a durable shell for the block.\n// Logic:\n// - If block has no existing jobId: starts a new job and attaches it\n// - If block has existing jobId with running job manager: reconnects to existing job\n// - If block has existing jobId with non-running job manager:\n//   - force=true: detaches old job and starts new one\n//   - force=false: returns without starting (leaves block unstarted)\n//\n// After establishing jobId, ensures job connection is active (reconnects if needed)\nfunc (dsc *DurableShellController) Start(ctx context.Context, blockMeta waveobj.MetaMapType, rtOpts *waveobj.RuntimeOpts, force bool) error {\n\tblockData, err := wstore.DBMustGet[*waveobj.Block](ctx, dsc.BlockId)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting block: %w\", err)\n\t}\n\n\tif conncontroller.IsLocalConnName(dsc.ConnName) {\n\t\treturn fmt.Errorf(\"durable shell controller requires a remote connection\")\n\t}\n\n\tvar jobId string\n\tif blockData.JobId != \"\" {\n\t\tstatus, err := jobcontroller.GetJobManagerStatus(ctx, blockData.JobId)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error getting job manager status: %w\", err)\n\t\t}\n\t\tif status == jobcontroller.JobManagerStatus_Running {\n\t\t\tjobId = blockData.JobId\n\t\t} else if !force {\n\t\t\tlog.Printf(\"block %q has jobId %s but manager is not running (status: %s), not starting (force=false)\\n\", dsc.BlockId, blockData.JobId, status)\n\t\t\treturn nil\n\t\t} else {","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/blockcontroller/durableshellcontroller.go#L124-L160","documentation":"DurableShellController.Start begins by loading its Block record with DBMustGet to read blockData.JobId. This error wraps any failure to fetch that Block from the wave store — the block row is missing or the DB read fails.","triggerScenarios":"Start is called on a controller whose BlockId no longer exists in the store (block closed/deleted concurrently) or the wavedb read errors.","commonSituations":"Block closed while a start was in flight; workspace deleted; DB corruption or a mismatched data directory after moving app data.","solutions":["Confirm the block still exists and hasn't been closed before starting its controller","Check wavedb integrity / that the app data directory matches the instance","Treat not-found as benign: skip starting the controller for closed blocks","Recreate the block if its record was deleted"],"exampleFix":"// before\ndsc.Start(ctx, meta, rtOpts, true)\n// after\nif _, err := wstore.DBGet[*waveobj.Block](ctx, dsc.BlockId); err != nil {\n    return // block gone; don't start\n}\ndsc.Start(ctx, meta, rtOpts, true)","handlingStrategy":"validation","validationCode":"if _, err := wstore.DBGet[*waveobj.Block](ctx, dsc.BlockId); err != nil {\n    return // block absent; do not start controller\n}","typeGuard":null,"tryCatchPattern":"if err := dsc.Start(ctx, meta, rtOpts, true); err != nil {\n    if strings.Contains(err.Error(), \"error getting block\") { return nil } // treat as closed\n}","preventionTips":["Stop durable shell controllers when their block is closed","Avoid starting controllers for blocks pending deletion","Verify wavedb path/data directory before launch"],"tags":["database","block","not-found","durable-shell"],"backgroundTag":"block-not-found","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}