{"record":{"id":"527fb5ae5c860c33","repo":"chenhg5/cc-connect","slug":"another-cc-connect-instance-is-already-running-pi","errorCode":null,"errorMessage":"another cc-connect instance is already running (PID %d) with config %s","messagePattern":"another cc-connect instance is already running \\(PID (.+?)\\) with config (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cc-connect/instance_lock.go","lineNumber":55,"sourceCode":"\t\treturn nil, fmt.Errorf(\"cannot create config directory: %w\", err)\n\t}\n\n\t// Open/create the lock file\n\tf, err := os.OpenFile(lockPath, os.O_CREATE|os.O_RDWR, 0644)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot open lock file: %w\", err)\n\t}\n\n\t// Try to acquire exclusive lock (non-blocking)\n\terr = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)\n\tif err != nil {\n\t\t// Lock is held by another process\n\t\tf.Close()\n\n\t\t// Try to read PID from lock file for better error message\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)\n\t}\n\n\t// Write our PID to the lock file for diagnostics\n\tpid := os.Getpid()\n\t_ = f.Truncate(0)\n\t_, _ = f.Seek(0, 0)\n\tfmt.Fprintf(f, \"%d\\n\", pid)\n\n\treturn &InstanceLock{\n\t\tfile:     f,\n\t\tpath:     lockPath,\n\t\tacquired: true,\n\t}, nil\n}\n\n// Release releases the instance lock. It is safe to call multiple times.","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/cmd/cc-connect/instance_lock.go#L37-L73","documentation":"AcquireInstanceLock takes an exclusive non-blocking flock; when it is already held, the lock file is parsed for a PID and this error reports the PID of the running instance plus the config path. It is an intentional, expected error meaning a second cc-connect instance is attempting to use the same config concurrently.","triggerScenarios":"Calling AcquireInstanceLock(configPath) while another live cc-connect process holds LOCK_EX on <configDir>/.<configBase>.lock and its PID was successfully read from the lock file.","commonSituations":"Starting a second daemon manually while a systemd/launchd service is running; a duplicated terminal run; a stale process that is actually still alive despite the user thinking it stopped.","solutions":["Verify the running instance: ps -p <PID> and stop it if unwanted (kill <PID> or systemctl stop cc-connect).","If you truly want a second instance, use a different --config path so a different lock file is used.","If PID is stale (process gone), remove the lock file and retry — flock is released automatically when the holder dies."],"exampleFix":"// shell\n// before\ncc-connect --config ~/.config/cc-connect/config.toml\n// after\nsystemctl --user stop cc-connect && cc-connect --config ~/.config/cc-connect/config.toml","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"lock, err := AcquireInstanceLock(configPath)\nif err != nil {\n    var pid int\n    if _, scanErr := fmt.Sscanf(err.Error(), \"another cc-connect instance is already running (PID %d)\", &pid); scanErr == nil {\n        fmt.Fprintf(os.Stderr, \"instance %d already running; stopping.\\n\", pid)\n    }\n    os.Exit(1)\n}","preventionTips":["Use systemd/launchd/supervisor so instances are started once and tracked.","Check service status before manual runs.","Use distinct --config paths for parallel instances."],"tags":["singleton","file-lock","process","cli"],"backgroundTag":"instance-already-running","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"}