# How to Troubleshoot Common Issues with croc: Complete Diagnostics Guide

> Troubleshoot common croc issues. Verify relay ports, set CROC_SECRET, bypass prompts with --yes, and enable debug for connection logs. Get croc running smoothly.

- Repository: [Zack/croc](https://github.com/schollz/croc)
- Tags: how-to-guide
- Published: 2026-07-26

---

**To troubleshoot common issues with croc, verify relay ports are free with `nc -zv`, ensure the `CROC_SECRET` environment variable is exported before running commands, bypass overwrite prompts using `--yes`, and enable `--debug` for detailed connection logs.**

croc is a Go-based peer-to-peer file transfer tool that encrypts data in transit using PAKE (Password Authenticated Key Exchange). When transfers fail or connections timeout, understanding the underlying architecture of the `schollz/croc` repository helps you pinpoint whether the issue lies in the relay layer, TCP engine, or CLI configuration. This guide walks through the most frequent failure modes and their exact fixes using the source code implementation.

## Understanding croc's Architecture

croc relies on five distinct components that work together to establish encrypted transfers. Knowing these boundaries makes it easier to isolate problems.

- **CLI** ([`src/cli/cli.go`](https://github.com/schollz/croc/blob/main/src/cli/cli.go)): Parses flags, builds the `croc.Options` struct, and launches the appropriate mode (send, receive, relay, or serve).
- **TCP Engine** ([`src/tcp/tcp.go`](https://github.com/schollz/croc/blob/main/src/tcp/tcp.go)): Handles the actual data streams between peers, performing the PAKE handshake, encryption, and resumable transfers.
- **Relay Layer** ([`src/croc/croc.go`](https://github.com/schollz/croc/blob/main/src/croc/croc.go)): Acts as a lightweight signaling proxy when direct connections fail (NAT traversal). It also manages the **local relay** unless the `--no-local` flag is used.
- **Web Relay** ([`src/webrelay/webrelay.go`](https://github.com/schollz/croc/blob/main/src/webrelay/webrelay.go)): Serves the browser-based UI and provides a WebSocket bridge to the relay.
- **Utility Package** ([`src/utils/utils.go`](https://github.com/schollz/croc/blob/main/src/utils/utils.go)): Provides helpers for IP discovery, configuration handling, hashing, and filename validation.

## Fixing croc Relay Connection Failures

### Resolving Port Conflicts (9009-9013)

The most common connection failure occurs when the default relay ports are already in use. You will see an error like:

```

error listening on 127.0.0.1:9009: bind: address already in use

```

According to the source code in [`src/tcp/tcp.go`](https://github.com/schollz/croc/blob/main/src/tcp/tcp.go) at line 145, the `tcp.Run` function returns `fmt.Errorf("error listening on %s: %w", addr, err)` when the listener cannot bind. To resolve this, specify free ports using the `--ports` flag:

```bash
croc --ports 9100,9101,9102 send file.txt

```

Verify port availability first:

```bash
nc -zv 127.0.0.1 9009-9013

```

### Configuring Custom Relay Addresses

If you specify an incorrect relay address, the client cannot reach the signaling server. The validation logic in [`src/webrelay/webrelay.go`](https://github.com/schollz/croc/blob/main/src/webrelay/webrelay.go) at line 159 (`webrelay.normalizeConfig`) errors when the host is empty or malformed. Always verify your relay configuration:

```bash
croc --relay myrelay.example.com send file.txt

```

Alternatively, set the `CROC_RELAY` environment variable to ensure consistency across sessions.

### Handling Firewall and Proxy Blocking

Outbound TCP or WebSocket traffic may be filtered by corporate firewalls. The TCP client uses `net.Dial` inside `tcp.ConnectToTCPServer`, and connection failures bubble up to the CLI as timeout errors. To bypass restrictions, route traffic through a SOCKS5 proxy:

```bash
croc --socks5 127.0.0.1:9050 send file.txt

```

Ensure the proxy supports TCP tunneling by testing it first:

```bash
nc -x 127.0.0.1:9050 -zv example.com 443

```

### Local Relay Startup Issues (--no-local)

When you use the `--no-local` flag, croc disables the embedded relay and requires an external relay to be reachable. The CLI decides whether to start a local relay in [`src/cli/cli.go`](https://github.com/schollz/croc/blob/main/src/cli/cli.go) between lines 660-670. If you see connection timeouts while using `--no-local`, either remove the flag to enable the local relay or provide a valid external relay address with `--relay`.

## Resolving croc Transfer and Authentication Errors

### Missing CROC_SECRET Environment Variable

If the transfer fails immediately with "no secret provided" or the secret appears in the process list (a security issue tracked in CVE-2023-43621), the CLI cannot read the `CROC_SECRET` environment variable. The relevant logic in [`src/cli/cli.go`](https://github.com/schollz/croc/blob/main/src/cli/cli.go) (lines 120-130) shows that the `--classic` flag enables permanent environment-variable mode. Fix this by exporting the variable before running croc:

```bash
export CROC_SECRET=code-phrase
croc receive

```

To enable this behavior permanently, run:

```bash
croc --classic

```

### Bypassing File Overwrite Prompts

By default, croc asks before overwriting existing files or resuming partial transfers. In [`src/cli/cli.go`](https://github.com/schollz/croc/blob/main/src/cli/cli.go) at line 141, the `--overwrite` boolean flag controls this behavior. To force overwrite without interaction, use:

```bash
croc --yes --overwrite <code-phrase>

```

To resume automatically without prompts (but keep existing files), use:

```bash
croc --yes <code-phrase>

```

### Fixing Invalid File Name Errors

You may encounter errors stating `basename cannot contain path separators` or `filename cannot be an absolute path`. The `utils.ValidateFileName` function in [`src/utils/utils.go`](https://github.com/schollz/croc/blob/main/src/utils/utils.go) (lines 954-959) validates each argument before transfer. These errors trigger when you provide absolute paths or embed directory separators in a single filename argument. Always use relative paths without leading slashes:

```bash
croc send ./myfile.txt

```

### Hash Mismatch and Resume Failures

If a resumed transfer aborts with `unexpected EOF` or `hash mismatch`, the source file likely changed while the transfer was paused. croc computes per-chunk hashes (SHA-256, XXHash, or IMO-hash) and stores state in temporary `.croc` files. The resume logic in [`src/comm/comm.go`](https://github.com/schollz/croc/blob/main/src/comm/comm.go) (referenced at line 27) verifies these hashes, and any discrepancy causes failure. To resolve:

1. Ensure the source file is not being modified during transfer.
2. Delete the partially-received `.croc` file on the receiver side and restart the transfer.

## Troubleshooting croc Web Client and Network Issues

### Web Relay Connection Problems

When accessing the embedded web UI at `http://localhost:5173`, you may see "relay unavailable". The `webrelay.Handler` function in [`src/webrelay/webrelay.go`](https://github.com/schollz/croc/blob/main/src/webrelay/webrelay.go) (line 238) checks that the requested port is in the allowlist; otherwise, it returns HTTP 403. Ensure the `--ports` flag includes the port you intend to use:

```bash
croc serve --ports 9009,9010

```

Verify the browser can reach the WebSocket endpoint:

```bash
curl -I https://croc.schollz.com/ws

```

### SOCKS5 Proxy Configuration

If `croc --socks5 "127.0.0.1:9050"` hangs indefinitely, the proxy is either unreachable or does not support TCP tunneling. The proxy handling occurs in [`src/tcp/tcp.go`](https://github.com/schollz/croc/blob/main/src/tcp/tcp.go) at line 279 during the relay handshake. Test the proxy with `nc` as shown above, or remove the `--socks5` flag to connect directly.

## Using Debug Logging to Diagnose croc

When standard troubleshooting does not reveal the issue, enable verbose logging. In [`src/cli/cli.go`](https://github.com/schollz/croc/blob/main/src/cli/cli.go) at line 134, the `--debug` flag sets the global logger to "debug" level (lines 255-257). This output includes detailed connection attempts, handshake status, and low-level TCP errors:

```bash
croc --debug send myfile.txt

```

## Quick Diagnostic Checklist for croc

Use this checklist to systematically eliminate common problems:

- **Relay port conflict**: Run `nc -zv localhost 9009-9013` to verify ports are free.
- **Missing secret**: Run `export CROC_SECRET=code-phrase` before receiving.
- **Overwrite prompts**: Add `--yes --overwrite` to skip interaction.
- **Invalid filename**: Use relative paths without leading `/` characters.
- **Resume hash mismatch**: Delete `.croc` state files and retry.
- **Web relay blocked**: Ensure the port is in the allowlist with `--ports`.
- **Proxy unreachable**: Test connectivity with `nc -x` before using `--socks5`.
- **Need detailed logs**: Append `--debug` to any command.

## Summary

- **Port conflicts** occur when 9009-9013 are occupied; use `--ports` to specify alternatives.
- **Authentication failures** happen when `CROC_SECRET` is not exported; use `--classic` to enforce this permanently.
- **Overwrite prompts** can be bypassed with `--yes` and `--overwrite` flags defined in [`src/cli/cli.go`](https://github.com/schollz/croc/blob/main/src/cli/cli.go).
- **Filename validation** rejects absolute paths and separators; use relative paths only.
- **Hash mismatches** during resume indicate source file modification; delete `.croc` files to restart.
- **Debug logging** via `--debug` provides detailed diagnostics from the TCP engine and relay layer.

## Frequently Asked Questions

### Why does croc fail with "address already in use"?

This error originates in [`src/tcp/tcp.go`](https://github.com/schollz/croc/blob/main/src/tcp/tcp.go) when the default relay ports (9009-9013) are occupied by another process. Specify unused ports with `--ports 9100,9101,9102` or stop the conflicting service.

### How do I prevent my secret from appearing in the process list?

Export the `CROC_SECRET` environment variable before running croc, or enable `--classic` mode (defined in [`src/cli/cli.go`](https://github.com/schollz/croc/blob/main/src/cli/cli.go) lines 120-130) to force environment-variable usage and prevent the secret from appearing as a command-line argument.

### Why does croc show "hash mismatch" when resuming a transfer?

This occurs when the source file changes after the initial transfer attempt. The resume logic in [`src/comm/comm.go`](https://github.com/schollz/croc/blob/main/src/comm/comm.go) validates per-chunk hashes stored in `.croc` state files. Delete the partial `.croc` file on the receiver and restart the transfer with a stable source file.

### How do I enable verbose logging to debug connection issues?

Add the `--debug` flag to any croc command. This sets the log level to debug in [`src/cli/cli.go`](https://github.com/schollz/croc/blob/main/src/cli/cli.go) (line 134) and outputs detailed information about the PAKE handshake, relay negotiation, and TCP connection attempts.