tailscale/tailscale · critical

API response too large

Error message

API response too large

What it means

logpolicy.LogsDir walks a fallback chain to find a directory for log state: $TS_LOGS_DIR, platform dirs (STATE_DIRECTORY under systemd, /var/lib/tailscale, Windows ProgramData/LocalAppData), os.UserCacheDir, then the working directory (unless '/'), and finally os.MkdirTemp("", "tailscaled-log-*"). This panic means every earlier option was unavailable AND creating a temp dir failed — the machine effectively offers no writable location, so tailscaled aborts at startup.

Source

Thrown at client/tailscale/tailscale.go:180

		req.Header.Set("User-Agent", c.UserAgent)
	}
	return c.httpClient().Do(req)
}

// sendRequest add the authentication key to the request and sends it. It
// receives the response and reads up to 10MB of it.
func (c *Client) sendRequest(req *http.Request) ([]byte, *http.Response, error) {
	resp, err := c.Do(req)
	if err != nil {
		return nil, resp, err
	}
	defer resp.Body.Close()

	// Read response. Limit the response to 10MB.
	body := io.LimitReader(resp.Body, maxReadSize+1)
	b, err := io.ReadAll(body)
	if len(b) > maxReadSize {
		err = errors.New("API response too large")
	}
	return b, resp, err
}

// ErrResponse is the HTTP error returned by the Tailscale server.
type ErrResponse struct {
	Status  int
	Message string
}

func (e ErrResponse) Error() string {
	return fmt.Sprintf("Status: %d, Message: %q", e.Status, e.Message)
}

// HandleErrorResponse decodes the error message from the server and returns
// an [ErrResponse] from it.
//
// Deprecated: use [tailscale.com/client/tailscale/v2] instead.

View on GitHub (pinned to cfe32b8be6)

Solutions

  1. Set TS_LOGS_DIR to an existing writable directory before starting tailscaled: `TS_LOGS_DIR=/var/log/tailscale tailscaled ...` (create the dir first).
  2. Fix the temp dir: ensure /tmp (or $TMPDIR) exists, is mounted rw, and the filesystem/inodes aren't full (`df -h /tmp; df -i /tmp`).
  3. If run under systemd, use the packaged unit with StateDirectory= (sets STATE_DIRECTORY) or add `StateDirectory=tailscale` to your unit.
  4. In containers, mount a writable volume at /var/lib/tailscale or /tmp, or export HOME/XDG_CACHE_HOME to a writable path so UserCacheDir succeeds.

Example fix

# before: read-only container, no writable anything
$ docker run --read-only tailscale/tailscaled
panic: no safe place found to store log state

# after: give it a writable state dir
$ docker run --read-only \
    -e TS_LOGS_DIR=/state/logs \
    -v tsstate:/state \
    tailscale/tailscaled
Defensive patterns

Strategy: validation

Validate before calling

// before starting tailscaled, prove some log dir is writable
func logDirWritable() error {
    for _, d := range []string{
        os.Getenv("TS_LOGS_DIR"),
        os.Getenv("STATE_DIRECTORY"),
        "/var/lib/tailscale",
        os.TempDir(),
    } {
        if d == "" {
            continue
        }
        if err := os.MkdirAll(d, 0o700); err == nil {
            f, err := os.CreateTemp(d, "probe-*")
            if err == nil {
                f.Close()
                os.Remove(f.Name())
                return nil
            }
        }
    }
    return fmt.Errorf("no writable log directory; set TS_LOGS_DIR")
}

Prevention

When it happens

Trigger: Starting tailscaled in an environment where $TS_LOGS_DIR is unset/invalid, STATE_DIRECTORY is empty, /var/lib/tailscale is unwritable, UserCacheDir fails (no HOME/XDG_CACHE_HOME), cwd is '/' (typical under service managers), and MkdirTemp fails: read-only or full /tmp (disk exhausted, inode exhaustion), TMPDIR pointing to a nonexistent/unwritable directory, or ulimit/process restrictions.

Common situations: Containers (distroless/read-only rootfs, no writable /tmp, missing HOME), embedded systems with full flash, hardened systems with noexec/nodev/ro /tmp mounts, misconfigured TMPDIR, disk-full incidents, running tailscaled by hand from '/' after stripping env.

Related errors


AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15). Data as JSON: /api/errors/bab3b9d632834b38. Report an issue: GitHub.