{"record":{"id":"326123eb4a772ac9","repo":"IceWhaleTech/CasaOS","slug":"err-error","errorCode":null,"errorMessage":"err.Error()","messagePattern":"err\\.Error\\(\\)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"route/v1/zerotier.go","lineNumber":26,"sourceCode":"\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/IceWhaleTech/CasaOS-Common/utils/logger\"\n\t\"github.com/IceWhaleTech/CasaOS/common\"\n\t\"github.com/IceWhaleTech/CasaOS/pkg/utils/httper\"\n\t\"github.com/labstack/echo/v4\"\n\t\"github.com/tidwall/gjson\"\n\t\"go.uber.org/zap\"\n)\n\nfunc ZerotierProxy(ctx echo.Context) error {\n\t// Read the port number from the file\n\tw := ctx.Response().Writer\n\tr := ctx.Request()\n\tport, err := ioutil.ReadFile(\"/var/lib/zerotier-one/zerotier-one.port\")\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t}\n\n\t// Get the request path and remove \"/zt\"\n\tpath := strings.TrimPrefix(r.URL.Path, \"/v1/zt\")\n\tfmt.Println(path)\n\n\t// Build the target URL\n\ttargetURL := fmt.Sprintf(\"http://localhost:%s%s\", strings.TrimSpace(string(port)), path)\n\n\t// Create a new request\n\treq, err := http.NewRequest(r.Method, targetURL, r.Body)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t}\n\n\t// Add the X-ZT1-AUTH header\n\tauthToken, err := ioutil.ReadFile(\"/var/lib/zerotier-one/authtoken.secret\")\n\tif err != nil {","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/IceWhaleTech/CasaOS/blob/0d3b2f444ec0193193cf03eef6d43c6e35b0183e/route/v1/zerotier.go#L8-L44","documentation":"In ZerotierProxy (route/v1/zerotier.go) this is the raw error surfaced when ioutil.ReadFile fails to read /var/lib/zerotier-one/zerotier-one.port, the file in which a running ZeroTier service publishes its local control-API port. http.Error() writes the message to the client, but the code does NOT return, so execution continues with a nil/empty port and produces a bogus target URL — the real defect this error reveals is the missing early return.","triggerScenarios":"GET/POST any /v1/zt/* route when (1) zerotier-one is not installed, (2) the service is stopped so the port file was never created/removed, (3) CasaOS runs as a user without read permission on /var/lib/zerotier-one, (4) ZeroTier version predates the port-file mechanism.","commonSituations":"Zerotier add-on removed but UI still issues proxy calls; fresh install where the user opened the ZT panel before starting the service; containerized CasaOS where /var/lib/zerotier-one is not bind-mounted from the host; permission hardening (chmod 700) on the zerotier state dir.","solutions":["Confirm zerotier-one is running (zerotier-cli info / systemctl status zerotier-one).","Verify the file exists and is readable: ls -l /var/lib/zerotier-one/zerotier-one.port.","Add `return` immediately after the http.Error call so a failed read does not cascade into an invalid proxy request.","When proxying from a container, bind-mount the host's /var/lib/zerotier-one into it."],"exampleFix":"// before\nport, err := ioutil.ReadFile(\"/var/lib/zerotier-one/zerotier-one.port\")\nif err != nil {\n    http.Error(w, err.Error(), http.StatusInternalServerError)\n}\n\n// after\nport, err := os.ReadFile(\"/var/lib/zerotier-one/zerotier-one.port\")\nif err != nil {\n    http.Error(w, \"zerotier service not available: \"+err.Error(), http.StatusInternalServerError)\n    return\n}","handlingStrategy":"validation","validationCode":"// before proxying any /v1/zt request\nportBytes, err := os.ReadFile(\"/var/lib/zerotier-one/zerotier-one.port\")\nif err != nil {\n    // service down: fail fast with a clean message instead of proxying\n    return ctx.String(http.StatusServiceUnavailable, \"zerotier-one service is not running\")\n}\nport := strings.TrimSpace(string(portBytes))\nif _, err := strconv.Atoi(port); err != nil {\n    return ctx.String(http.StatusServiceUnavailable, \"zerotier port file invalid\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always `return` after http.Error in Echo/net-http handlers — the response writer does not stop execution.","Check zerotier-one service state before enabling the ZT UI panel.","When containerized, bind-mount the host /var/lib/zerotier-one into the CasaOS container.","Replace deprecated ioutil with os."],"tags":["zerotier","proxy","file-io","missing-return","casaos"],"backgroundTag":null,"analyzedSha":"0d3b2f444ec0193193cf03eef6d43c6e35b0183e","analyzedAt":"2026-08-15T13:27:57.821Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}