chenhg5/cc-connect · error

cannot convert lock path: %w

Error message

cannot convert lock path: %w

What it means

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.

Source

Thrown at cmd/cc-connect/instance_lock_windows.go:36

type InstanceLock struct {
	handle   syscall.Handle
	path     string
	acquired bool
}

func AcquireInstanceLock(configPath string) (*InstanceLock, error) {
	configDir := filepath.Dir(configPath)
	configBase := filepath.Base(configPath)
	lockName := fmt.Sprintf(".%s.lock", configBase)
	lockPath := filepath.Join(configDir, lockName)

	if err := os.MkdirAll(configDir, 0755); err != nil {
		return nil, fmt.Errorf("cannot create config directory: %w", err)
	}

	pathPtr, err := syscall.UTF16PtrFromString(lockPath)
	if err != nil {
		return nil, fmt.Errorf("cannot convert lock path: %w", err)
	}

	handle, createErr := syscall.CreateFile(
		pathPtr,
		syscall.GENERIC_READ|syscall.GENERIC_WRITE,
		syscall.FILE_SHARE_READ,
		nil,
		syscall.OPEN_ALWAYS,
		syscall.FILE_ATTRIBUTE_NORMAL,
		0,
	)

	if createErr != nil {
		pid := readPIDFromLockFile(lockPath)
		if pid > 0 {
			return nil, fmt.Errorf("another cc-connect instance is already running (PID %d) with config %s", pid, configPath)
		}
		return nil, fmt.Errorf("another cc-connect instance is already running with config %s", configPath)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the --config argument/env var for stray NUL bytes; pass a clean path.
  2. Re-check how the wrapper/service constructs the path (trim nulls: strings.Trim(path, "\x00") at the caller).
  3. Test with a simple ASCII path to isolate encoding issues from permissions.

Example fix

// before
lockPath := cfgPath + "\x00" // NUL sneaks in from parsing
// after
lockPath := strings.TrimRight(cfgPath, "\x00")
Defensive patterns

Strategy: validation

Validate before calling

if strings.ContainsRune(lockPath, 0) {
    return fmt.Errorf("lock path contains NUL byte: %q", lockPath)
}

Try / catch

lock, err := AcquireInstanceLock(configPath)
if err != nil && strings.Contains(err.Error(), "cannot convert lock path") {
    slog.Error("config path has embedded NUL byte", "pathLen", len(configPath))
    os.Exit(1)
}

Prevention

When it happens

Trigger: The constructed lock path <configDir>\. <configBase>.lock contains a NUL byte, typically because configPath (from a flag/env) contained '\x00'.

Common situations: A mis-encoded config path coming from an environment variable or a wrapper script passing corrupted arguments; very rare in practice.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/1ad422be86e1b3cc. Report an issue: GitHub.