router-for-me/CLIProxyAPI · error

failed to write token to file: %w

Error message

failed to write token to file: %w

What it means

The token file was created but json.NewEncoder(f).Encode(data) failed while serializing or writing the credential. Two distinct causes hide here: a JSON marshal error on the merged data (non-serializable field — same class as error 191) or an I/O write error (disk full, quota exceeded) since the encoder writes directly to the file.

Source

Thrown at internal/auth/claude/token.go:101

	data, errMerge := misc.MergeMetadata(ts, ts.Metadata)
	if errMerge != nil {
		return fmt.Errorf("failed to merge metadata: %w", errMerge)
	}

	// Create the token file
	f, err := os.Create(authFilePath)
	if err != nil {
		return fmt.Errorf("failed to create token file: %w", err)
	}
	defer func() {
		if errClose := f.Close(); errClose != nil {
			log.Errorf("claude token storage: close token file error: %v", errClose)
		}
	}()

	// Encode and write the token data as JSON
	if err = json.NewEncoder(f).Encode(data); err != nil {
		return fmt.Errorf("failed to write token to file: %w", err)
	}
	return nil
}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Check the wrapped error: *json.MarshalTypeError/UnsupportedTypeError → remove the non-serializable field (see error 191 fixes); 'no space left on device' → free space or move auth-dir to a bigger volume.
  2. Validate serializability before saving with a json.Marshal of the merged data in a test.
  3. Monitor disk usage on the auth-dir volume; keep credentials off the container root layer.
Defensive patterns

Strategy: try-catch

Validate before calling

data, err := misc.MergeMetadata(ts, ts.Metadata)
if err != nil { return err }
if _, err := json.Marshal(data); err != nil { return fmt.Errorf("credential not serializable: %w", err) }

Try / catch

if err := ts.SaveTokenToFile(p); err != nil {
    if strings.Contains(err.Error(), "failed to write token") {
        // distinguish disk-full from marshal failure via the wrapped error
        if errors.Is(err, syscall.ENOSPC) { /* free space, retry */ } else { /* fix data model */ }
    }
}

Prevention

When it happens

Trigger: Merged token data contains a value JSON cannot marshal; or the filesystem fills up (ENOSPC), quota is hit, or the volume is yanked mid-write precisely between Create and Encode.

Common situations: Disk-full on small containers/VMs where auth-dir shares the root volume; embedding users adding func-typed exported fields to the storage struct; NFS quirks with delayed allocation; the defer-close then logs a secondary close error confirming a bad stream state.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/0982bd7656c841f8. Report an issue: GitHub.