chenhg5/cc-connect · error

codex app-server: save image: %w

Error message

codex app-server: save image: %w

What it means

After creating the image directory the session writes each image to disk with os.WriteFile; a failure here is wrapped as 'save image'. This indicates the directory was created but an individual file write failed — typically permissions, disk space, or a race removing the directory mid-write.

Source

Thrown at agent/codex/appserver_session.go:530

}

func (s *appServerSession) stageImages(prompt string, images []core.ImageAttachment) (string, []string, error) {
	if len(images) == 0 {
		return prompt, nil, nil
	}

	imgDir := filepath.Join(s.workDir, ".cc-connect", "images")
	if err := os.MkdirAll(imgDir, 0o755); err != nil {
		return "", nil, fmt.Errorf("codex app-server: create image dir: %w", err)
	}

	imagePaths := make([]string, 0, len(images))
	for i, img := range images {
		ext := codexImageExt(img.MimeType)
		fname := fmt.Sprintf("img_%d_%d%s", time.Now().UnixMilli(), i, ext)
		fpath := filepath.Join(imgDir, fname)
		if err := os.WriteFile(fpath, img.Data, 0o644); err != nil {
			return "", nil, fmt.Errorf("codex app-server: save image: %w", err)
		}
		imagePaths = append(imagePaths, fpath)
	}

	if strings.TrimSpace(prompt) == "" {
		prompt = "Please analyze the attached image(s)."
	}

	return prompt, imagePaths, nil
}

func (s *appServerSession) RespondPermission(requestID string, result core.PermissionResult) error {
	s.approvalsMu.Lock()
	ch := s.pendingApprovals[requestID]
	s.approvalsMu.Unlock()
	if ch == nil {
		return fmt.Errorf("codex app-server: no pending approval for request %s", requestID)
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check disk space and quota on the volume holding workDir (df -h)
  2. Ensure the process user has write permission on .cc-connect/images and no security module blocks writes
  3. Stop concurrent cleanup jobs touching .cc-connect while a session is active
  4. Check the wrapped errno in the error string (ENOSPC, EACCES, ENOENT) to target the fix

Example fix

// before
if err := os.WriteFile(fpath, img.Data, 0o644); err != nil {
    return "", nil, fmt.Errorf("codex app-server: save image: %w", err)
}
// after
if err := os.WriteFile(fpath, img.Data, 0o644); err != nil {
    slog.Warn("image save failed", "path", fpath, "bytes", len(img.Data), "error", err)
    return "", nil, fmt.Errorf("codex app-server: save image %s: %w", fpath, err)
}
Defensive patterns

Strategy: validation

Validate before calling

fi, err := os.Stat(imgDir)
if err != nil || !fi.IsDir() {
    return fmt.Errorf("image dir missing or not a directory: %s", imgDir)
}
test, err := os.CreateTemp(imgDir, "wtest*")
if err != nil { return fmt.Errorf("image dir not writable: %w", err) }
test.Close(); os.Remove(test.Name())

Prevention

When it happens

Trigger: os.WriteFile(fpath, img.Data, 0o644) fails while persisting an attachment inside <workDir>/.cc-connect/images before sending it to the app-server.

Common situations: Disk quota/full disk when saving large images; another process (cleanup cron) deleting .cc-connect/images concurrently; restrictive umask or SELinux/AppArmor blocking writes; filename collision overwriting is not the issue but ENOSPC/EDQUOT commonly is.

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/eaf5fb26bf41a5cd. Report an issue: GitHub.