plandex-ai/plandex · error

error writing convo message description: %v

Error message

error writing convo message description: %v

What it means

After marshaling, StoreDescription writes the JSON to descriptionsDir/<id>.json via os.WriteFile. This error wraps any OS-level failure of that write: permissions, missing directory, disk full, or I/O errors.

Source

Thrown at app/server/db/plan_helpers.go:346

	now := time.Now()

	if description.Id == "" {
		description.Id = uuid.New().String()
		description.CreatedAt = now
	}
	description.UpdatedAt = now

	bytes, err := json.Marshal(description)

	if err != nil {
		return fmt.Errorf("error marshalling convo message description: %v", err)
	}

	err = os.WriteFile(filepath.Join(descriptionsDir, description.Id+".json"), bytes, os.ModePerm)

	if err != nil {
		return fmt.Errorf("error writing convo message description: %v", err)
	}

	return nil
}

func DeleteDraftPlans(orgId, projectId, userId string) error {
	res, err := Conn.Query("DELETE FROM plans WHERE project_id = $1 AND owner_id = $2 AND name = 'draft' RETURNING id;", projectId, userId)
	if err != nil {
		return fmt.Errorf("error deleting draft plans: %v", err)
	}

	defer res.Close()

	// get ids
	var ids []string

	for res.Next() {
		var id string

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check the wrapped OS error (ENOSPC, EACCES) and fix storage capacity/permissions
  2. Verify description.Id is non-empty before writing
  3. Ensure directory creation and write use consistent, non-racy lifecycle (don't delete plan dir concurrently)
  4. Use a safer permission mode (e.g. 0o644) instead of os.ModePerm on the file
  5. Mount the storage volume read-write and monitor disk usage

Example fix

// before
if description.Id == "" {
    // proceeds and writes ".json"
}
err = os.WriteFile(filepath.Join(descriptionsDir, description.Id+".json"), bytes, os.ModePerm)
// after
if description.Id == "" {
    return fmt.Errorf("cannot store description: empty id")
}
if err := os.WriteFile(filepath.Join(descriptionsDir, description.Id+".json"), bytes, 0o644); err != nil {
    return fmt.Errorf("error writing convo message description: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

if description.Id == "" {
    return fmt.Errorf("description id is empty")
}
if err := validateDirWritable(descriptionsDir); err != nil {
    return err
}

Try / catch

if err := StoreDescription(desc); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOSPC) {
        // free disk space / alert ops
    }
    return err
}

Prevention

When it happens

Trigger: os.WriteFile(filepath.Join(descriptionsDir, description.Id+".json"), bytes, os.ModePerm) fails: directory was removed between MkdirAll and the write, permission denied, ENOSPC (disk full), description.Id is empty producing ".json", or read-only filesystem.

Common situations: Disk quota exceeded on the storage volume; concurrent DeletePlanDir removing the plan directory while a description write is in flight; empty Id due to upstream data bug; container filesystem mounted read-only after crash recovery.

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 plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/abac5ab4a1559ece. Report an issue: GitHub.