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
- Set TS_LOGS_DIR to an existing writable directory before starting tailscaled: `TS_LOGS_DIR=/var/log/tailscale tailscaled ...` (create the dir first).
- 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`).
- If run under systemd, use the packaged unit with StateDirectory= (sets STATE_DIRECTORY) or add `StateDirectory=tailscale` to your unit.
- 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
- Always set TS_LOGS_DIR (or STATE_DIRECTORY under systemd) to a dedicated writable volume in containers and embedded hosts.
- Monitor disk and inode usage on / and /tmp — MkdirTemp fails silently to the panic path when either is exhausted.
- Keep TMPDIR pointing at an existing, rw-mounted directory in service environments.
- Bake `mkdir -p /var/lib/tailscale` into container images so the default chain succeeds.
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
- unsupported init system '%s'
- failed creating systemd user dir: %w
- failed writing systemd user service: %w
- unable to create desktop file: %w
- unable to create tuntap device file: %w
AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15).
Data as JSON: /api/errors/bab3b9d632834b38.
Report an issue: GitHub.