chenhg5/cc-connect · error

pico2wave: create temp file: %w

Error message

pico2wave: create temp file: %w

What it means

PicoTTS.Synthesize first creates a temporary WAV file (os.CreateTemp with pattern pico_tts_*.wav) that pico2wave will write into; this error wraps the failure of that temp-file creation. It almost always indicates a filesystem-level problem: the OS temp directory does not exist, is full, or the process lacks write permission to it — often because TMPDIR/TEMP points somewhere unwritable.

Source

Thrown at core/tts.go:621

	}
	return &PicoTTS{
		Path:  path,
		Voice: voice,
	}
}

// Synthesize uses pico2wave to convert text to WAV audio bytes.
// pico2wave produces much better quality than espeak.
func (p *PicoTTS) Synthesize(ctx context.Context, text string, opts TTSSynthesisOpts) ([]byte, string, error) {
	voice := opts.Voice
	if voice == "" {
		voice = p.Voice
	}

	// Create secure temp file for pico2wave output
	tmpFile, err := os.CreateTemp("", "pico_tts_*.wav")
	if err != nil {
		return nil, "", fmt.Errorf("pico2wave: create temp file: %w", err)
	}
	tmpPath := tmpFile.Name()
	tmpFile.Close()
	defer os.Remove(tmpPath)

	// Build pico2wave command
	// --lang: language code (zh-CN for Chinese, en-US for English)
	// --wave: output WAV file path
	args := []string{
		"--lang=" + voice,
		"--wave=" + tmpPath,
		text,
	}

	// Execute pico2wave command
	cmd := exec.CommandContext(ctx, p.Path, args...)
	output, err := cmd.CombinedOutput()
	if err != nil {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check the temp directory: `echo $TMPDIR`, `df -h /tmp`, `touch /tmp/x` to confirm writability; fix TMPDIR or free space.
  2. For systemd deployments, add the temp dir to ReadWritePaths= or adjust PrivateTmp restrictions.
  3. Mount a writable tmpfs at /tmp in the container (e.g. docker run --tmpfs /tmp) or make the filesystem writable.
  4. As a fallback, pass an application-configured writable directory to os.CreateTemp instead of the OS default.

Example fix

// before
# systemd unit
ReadWritePaths=/var/lib/cc-connect   # /tmp not writable
// after
# systemd unit
ReadWritePaths=/var/lib/cc-connect /tmp
# or in code: honor a configurable temp dir
// dir := configuredTempDir (defaults to os.TempDir())
tmpFile, err := os.CreateTemp(dir, "pico_tts_*.wav")
Defensive patterns

Strategy: validation

Validate before calling

// Go: verify a writable temp dir before synthesis
probe, err := os.CreateTemp(os.TempDir(), "pico_probe_*.tmp")
if err != nil {
	return fmt.Errorf("no writable temp dir: %w", err)
}
name := probe.Name()
probe.Close()
os.Remove(name)

Try / catch

audio, format, err := pico.Synthesize(ctx, text, opts)
if err != nil {
	if strings.Contains(err.Error(), "create temp file") {
		// check TMPDIR, disk space, permissions before retrying
		log.Printf("temp dir unwritable: TMPDIR=%s err=%v", os.TempDir(), err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling Synthesize via PicoTTS when os.CreateTemp("", ...) fails: TMPDIR set to a nonexistent or read-only directory, /tmp full or mounted read-only, disk quota exhausted, or running in a sandbox with no writable temp dir.

Common situations: Docker/Kubernetes containers with a read-only root filesystem and no tmpfs at /tmp; systemd services with PrivateTmp or restrictive ReadWritePaths; TMPDIR exported to a deleted directory; disk-full conditions on long-running hosts.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/52e36ec6fe735318. Report an issue: GitHub.