{"record":{"id":"b2226a5cdd3e79c4","repo":"wavetermdev/waveterm","slug":"file-info-is-required-b2226a","errorCode":null,"errorMessage":"file info is required","messagePattern":"file info is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/remote/fileshare/wshfs/wshfs.go","lineNumber":45,"sourceCode":"\tMergeRequiredError          = \"directory already exists at %q, set overwrite flag to delete the existing contents or set merge flag to merge the contents\"\n\tOverwriteRequiredError      = \"file already exists at %q, set overwrite flag to delete the existing file\"\n)\n\n// This needs to be set by whoever initializes the client, either main-server or wshcmd-connserver\nvar RpcClient *wshutil.WshRpc\nvar RpcClientRouteId string\n\nfunc parseConnection(ctx context.Context, path string) (*connparse.Connection, error) {\n\tconn, err := connparse.ParseURIAndReplaceCurrentHost(ctx, path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing connection %s: %w\", path, err)\n\t}\n\treturn conn, nil\n}\n\nfunc Read(ctx context.Context, data wshrpc.FileData) (*wshrpc.FileData, error) {\n\tif data.Info == nil {\n\t\treturn nil, fmt.Errorf(\"file info is required\")\n\t}\n\tlog.Printf(\"Read: %v\", data.Info.Path)\n\tconn, err := parseConnection(ctx, data.Info.Path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tbroker := RpcClient.StreamBroker\n\tif broker == nil {\n\t\treturn nil, fmt.Errorf(\"stream broker not available\")\n\t}\n\tif RpcClientRouteId == \"\" {\n\t\treturn nil, fmt.Errorf(\"no route id available\")\n\t}\n\treaderRouteId := RpcClientRouteId\n\twriterRouteId := wshutil.MakeConnectionRouteId(conn.Host)\n\treader, streamMeta := broker.CreateStreamReader(readerRouteId, writerRouteId, 256*1024)\n\tdefer reader.Close()\n\tgo func() {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/remote/fileshare/wshfs/wshfs.go#L27-L63","documentation":"Read requires the FileData to carry a non-nil Info struct describing the file to read. When data.Info is nil, wshfs cannot determine which path to read and immediately fails with this sentinel error before any RPC is made. It is a guard against a malformed client request.","triggerScenarios":"Calling wshfs.Read(ctx, wshrpc.FileData{...}) without populating the Info field (e.g. FileData{Data64: ...} or a zero-value FileData), typically via FileReadCommand over RPC.","commonSituations":"Constructing the RPC payload by hand and forgetting Info; deserializing a request where the info field was dropped; copying example code that only sets Data64.","solutions":["Always set data.Info with at least Info.Path populated before calling Read","If receiving this over RPC, check the client is serializing the info field","Add a nil check on Info in your wrapper before invoking Read for a clearer error"],"exampleFix":"// before\nwshfs.Read(ctx, wshrpc.FileData{At: &wshrpc.FileRange{Offset: 0, Size: 1024}})\n// after\nwshfs.Read(ctx, wshrpc.FileData{Info: &wshrpc.FileInfo{Path: \"wsh://host/tmp/f.txt\"}, At: &wshrpc.FileRange{Offset: 0, Size: 1024}})","handlingStrategy":"validation","validationCode":"if data.Info == nil || data.Info.Path == \"\" {\n    return errors.New(\"FileData.Info with a Path is required for wshfs.Read\")\n}","typeGuard":"func hasFileInfo(d wshrpc.FileData) bool {\n    return d.Info != nil && d.Info.Path != \"\"\n}","tryCatchPattern":"out, err := wshfs.Read(ctx, data)\nif err != nil {\n    if strings.Contains(err.Error(), \"file info is required\") {\n        return fmt.Errorf(\"caller bug: FileData.Info was nil: %w\", err)\n    }\n    return err\n}","preventionTips":["Use constructors that always set Info (e.g. from Stat results)","Never pass a zero-value FileData to Read","Add a pre-call assertion in wrapper functions around wshfs","Enable linting/nil-check review on RPC payload construction"],"tags":["go","validation","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}