{"record":{"id":"1ad422be86e1b3cc","repo":"chenhg5/cc-connect","slug":"cannot-convert-lock-path-w","errorCode":null,"errorMessage":"cannot convert lock path: %w","messagePattern":"cannot convert lock path: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cc-connect/instance_lock_windows.go","lineNumber":36,"sourceCode":"type InstanceLock struct {\n\thandle   syscall.Handle\n\tpath     string\n\tacquired bool\n}\n\nfunc AcquireInstanceLock(configPath string) (*InstanceLock, error) {\n\tconfigDir := filepath.Dir(configPath)\n\tconfigBase := filepath.Base(configPath)\n\tlockName := fmt.Sprintf(\".%s.lock\", configBase)\n\tlockPath := filepath.Join(configDir, lockName)\n\n\tif err := os.MkdirAll(configDir, 0755); err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot create config directory: %w\", err)\n\t}\n\n\tpathPtr, err := syscall.UTF16PtrFromString(lockPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot convert lock path: %w\", err)\n\t}\n\n\thandle, createErr := syscall.CreateFile(\n\t\tpathPtr,\n\t\tsyscall.GENERIC_READ|syscall.GENERIC_WRITE,\n\t\tsyscall.FILE_SHARE_READ,\n\t\tnil,\n\t\tsyscall.OPEN_ALWAYS,\n\t\tsyscall.FILE_ATTRIBUTE_NORMAL,\n\t\t0,\n\t)\n\n\tif createErr != nil {\n\t\tpid := readPIDFromLockFile(lockPath)\n\t\tif pid > 0 {\n\t\t\treturn nil, fmt.Errorf(\"another cc-connect instance is already running (PID %d) with config %s\", pid, configPath)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"another cc-connect instance is already running with config %s\", configPath)","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/cmd/cc-connect/instance_lock_windows.go#L18-L54","documentation":"On the Windows path of AcquireInstanceLock, syscall.UTF16PtrFromString(lockPath) failed before opening the handle, wrapped as \"cannot convert lock path: %w\". This API errors only when the path contains an interior NUL (0x00) byte, which cannot be represented in a NUL-terminated UTF-16 Win32 path.","triggerScenarios":"The constructed lock path <configDir>\\. <configBase>.lock contains a NUL byte, typically because configPath (from a flag/env) contained '\\x00'.","commonSituations":"A mis-encoded config path coming from an environment variable or a wrapper script passing corrupted arguments; very rare in practice.","solutions":["Inspect the --config argument/env var for stray NUL bytes; pass a clean path.","Re-check how the wrapper/service constructs the path (trim nulls: strings.Trim(path, \"\\x00\") at the caller).","Test with a simple ASCII path to isolate encoding issues from permissions."],"exampleFix":"// before\nlockPath := cfgPath + \"\\x00\" // NUL sneaks in from parsing\n// after\nlockPath := strings.TrimRight(cfgPath, \"\\x00\")","handlingStrategy":"validation","validationCode":"if strings.ContainsRune(lockPath, 0) {\n    return fmt.Errorf(\"lock path contains NUL byte: %q\", lockPath)\n}","typeGuard":null,"tryCatchPattern":"lock, err := AcquireInstanceLock(configPath)\nif err != nil && strings.Contains(err.Error(), \"cannot convert lock path\") {\n    slog.Error(\"config path has embedded NUL byte\", \"pathLen\", len(configPath))\n    os.Exit(1)\n}","preventionTips":["Sanitize configPath from env/args (strip \\x00) before passing in.","Prefer flags over parsed binary blobs for path input.","Test Windows builds with simple ASCII paths."],"tags":["windows","path","encoding","cli"],"backgroundTag":"invalid-url-format","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}