{"record":{"id":"2e921afd9630f0bd","repo":"wavetermdev/waveterm","slug":"blockdef-is-nil","errorCode":null,"errorMessage":"blockDef is nil","messagePattern":"blockDef is nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wcore/block.go","lineNumber":26,"sourceCode":"\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\t\"github.com/google/uuid\"\n\t\"github.com/wavetermdev/waveterm/pkg/filestore\"\n\t\"github.com/wavetermdev/waveterm/pkg/panichandler\"\n\t\"github.com/wavetermdev/waveterm/pkg/telemetry\"\n\t\"github.com/wavetermdev/waveterm/pkg/telemetry/telemetrydata\"\n\t\"github.com/wavetermdev/waveterm/pkg/util/utilfn\"\n\t\"github.com/wavetermdev/waveterm/pkg/waveobj\"\n\t\"github.com/wavetermdev/waveterm/pkg/wps\"\n\t\"github.com/wavetermdev/waveterm/pkg/wshrpc\"\n\t\"github.com/wavetermdev/waveterm/pkg/wstore\"\n)\n\nfunc CreateSubBlock(ctx context.Context, blockId string, blockDef *waveobj.BlockDef) (*waveobj.Block, error) {\n\tif blockDef == nil {\n\t\treturn nil, fmt.Errorf(\"blockDef is nil\")\n\t}\n\tif blockDef.Meta == nil || blockDef.Meta.GetString(waveobj.MetaKey_View, \"\") == \"\" {\n\t\treturn nil, fmt.Errorf(\"no view provided for new block\")\n\t}\n\tblockData, err := createSubBlockObj(ctx, blockId, blockDef)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating sub block: %w\", err)\n\t}\n\tblockView := blockDef.Meta.GetString(waveobj.MetaKey_View, \"\")\n\tblockController := blockDef.Meta.GetString(waveobj.MetaKey_Controller, \"\")\n\tgo recordBlockCreationTelemetry(blockView, blockController, true)\n\treturn blockData, nil\n}\n\nfunc createSubBlockObj(ctx context.Context, parentBlockId string, blockDef *waveobj.BlockDef) (*waveobj.Block, error) {\n\treturn wstore.WithTxRtn(ctx, func(tx *wstore.TxWrap) (*waveobj.Block, error) {\n\t\tparentBlock, _ := wstore.DBGet[*waveobj.Block](tx.Context(), parentBlockId)\n\t\tif parentBlock == nil {","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wcore/block.go#L8-L44","documentation":"CreateSubBlock rejects a nil BlockDef up front. The RPC command CreateSubBlockCommand passes the caller-supplied block definition straight through, so a null definition reaches the core without any view, metadata, or files to create a block from.","triggerScenarios":"Calling CreateSubBlock / CreateSubBlockCommand with blockDef == nil, e.g. a client RPC payload where the blockdef field was omitted or deserialized to null.","commonSituations":"Scripts or frontend code calling the wsh create-subblock RPC without a body; an automation tool sending a partially-built command object.","solutions":["Always construct and pass a full waveobj.BlockDef with a Meta map containing MetaKey_View","In the calling command handler, check the parsed argument for nil before invoking CreateSubBlock","If the definition comes from external input, unmarshal and validate it before the RPC call"],"exampleFix":"// before\nblock, err := wcore.CreateSubBlock(ctx, blockId, nil)\n// after\nblockDef := &waveobj.BlockDef{Meta: waveobj.MetaMapType{waveobj.MetaKey_View: \"term\"}}\nblock, err := wcore.CreateSubBlock(ctx, blockId, blockDef)","handlingStrategy":"validation","validationCode":"if blockDef == nil {\n    return nil, errors.New(\"caller bug: blockDef must be provided\")\n}","typeGuard":"func hasBlockDef(d *waveobj.BlockDef) bool { return d != nil }","tryCatchPattern":"block, err := wcore.CreateSubBlock(ctx, blockId, blockDef)\nif err != nil && err.Error() == \"blockDef is nil\" {\n    // construct a valid BlockDef and retry\n}","preventionTips":["Never pass nullable blockdef values straight from RPC payloads into core APIs","Validate RPC command arguments before dispatching","Use constructors/helpers that always produce a complete BlockDef"],"tags":["nil-argument","blocks","wave-terminal"],"backgroundTag":"nil-argument-validation","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}