{"record":{"id":"345709112fb23661","repo":"wavetermdev/waveterm","slug":"stream-broker-route-id-not-available-for-file-copy","errorCode":null,"errorMessage":"stream broker route id not available for file copy","messagePattern":"stream broker route id not available for file copy","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshrpc/wshremote/wshremote_file.go","lineNumber":172,"sourceCode":"\t\treturn false, fmt.Errorf(\"copying directories is not supported\")\n\t}\n\tif srcFileInfo.Size > RemoteFileTransferSizeLimit {\n\t\treturn false, fmt.Errorf(\"file %q size %d exceeds transfer limit of %d bytes\", data.SrcUri, srcFileInfo.Size, RemoteFileTransferSizeLimit)\n\t}\n\n\tdestFilePath, err := prepareDestForCopy(destPathCleaned, fspath.Base(srcConn.Path), destHasSlash, opts.Overwrite)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tdestFile, err := os.OpenFile(destFilePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, srcFileInfo.Mode)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"cannot create destination file %q: %w\", destFilePath, err)\n\t}\n\tdefer destFile.Close()\n\n\tif wshfs.RpcClientRouteId == \"\" {\n\t\treturn false, fmt.Errorf(\"stream broker route id not available for file copy\")\n\t}\n\twriterRouteId := wshutil.MakeConnectionRouteId(srcConn.Host)\n\treader, streamMeta := wshfs.RpcClient.StreamBroker.CreateStreamReader(wshfs.RpcClientRouteId, writerRouteId, 256*1024)\n\tlog.Printf(\"RemoteFileCopyCommand: readroute=%s writeroute=%s\", streamMeta.ReaderRouteId, streamMeta.WriterRouteId)\n\tdefer reader.Close()\n\tgo func() {\n\t\t<-readCtx.Done()\n\t\treader.Close()\n\t}()\n\tstreamData := wshrpc.CommandRemoteFileStreamData{\n\t\tPath:       srcConn.Path,\n\t\tStreamMeta: *streamMeta,\n\t}\n\tif _, err = wshclient.RemoteFileStreamCommand(wshfs.RpcClient, streamData, &wshrpc.RpcOpts{Route: writerRouteId}); err != nil {\n\t\treturn false, fmt.Errorf(\"error starting file stream for %q: %w\", data.SrcUri, err)\n\t}\n\tif _, err = io.Copy(destFile, reader); err != nil {\n\t\treturn false, fmt.Errorf(\"error copying file %q to %q: %w\", data.SrcUri, data.DestUri, err)","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshrpc/wshremote/wshremote_file.go#L154-L190","documentation":"Before streaming the file, the command checks that wshfs.RpcClientRouteId is set — the route id of the local RPC client registered with the stream broker. If it is empty, no stream route has been established for this client and the streaming copy cannot proceed. This indicates the wsh RPC client was not fully initialized (broker registration not done) at the time of the call.","triggerScenarios":"RemoteFileCopyCommand reaches the stream setup on the local side while wshfs.RpcClientRouteId == \"\", i.e. the RpcClient exists but its route id was never assigned/registered with StreamBroker, typically because the wsh client/broker bootstrap hasn't completed in this process.","commonSituations":"Calling the copy command very early in client startup before the RPC client route registration completes; using the wshremote server machinery outside a fully initialized Wave/wsh environment; a regression where RpcClient is created without StreamBroker registration.","solutions":["Ensure the wsh RPC client is fully initialized (RpcClient registered with StreamBroker, RpcClientRouteId set) before invoking file copy commands.","Wait for connection/client bootstrap to complete in your app before issuing copy commands.","If embedding the package, register the client route the same way wsh main initialization does (StreamBroker.CreateStreamReader/Writer flow requires a non-empty local route id).","Upgrade Wave Terminal if a version change caused the client route to no longer be set automatically."],"exampleFix":"// before\nok, err := srv.RemoteFileCopyCommand(ctx, copyData) // run immediately after start\n// after\nif wshfs.RpcClientRouteId == \"\" {\n    time.Sleep(500 * time.Millisecond) // or wait on client-ready signal\n}\nok, err := srv.RemoteFileCopyCommand(ctx, copyData)","handlingStrategy":"try-catch","validationCode":"if wshfs.RpcClient == nil || wshfs.RpcClientRouteId == \"\" {\n    return errors.New(\"wsh rpc client not initialized; wait for client bootstrap before copying\")\n}","typeGuard":"func streamBrokerReady(rpc *wshutil.WshRpc) bool { return rpc != nil && wshfs.RpcClientRouteId != \"\" }","tryCatchPattern":"ok, err := RemoteFileCopyCommand(ctx, data)\nif err != nil {\n    if strings.Contains(err.Error(), \"stream broker route id not available\") {\n        // retry after client bootstrap completes, or surface an init-order bug\n    }\n    return err\n}","preventionTips":["Initialize and register the wsh RPC client (setting wshfs.RpcClientRouteId) before any file operations.","Gate file-copy calls behind a client-ready signal/event rather than firing at startup.","Verify StreamBroker registration during local development of embedded wsh usage.","Log client route id at startup to catch init-order regressions early."],"tags":["file-copy","rpc","stream-broker","initialization","wave-terminal"],"backgroundTag":"rpc-route-not-initialized","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}