wavetermdev/waveterm · error

failed to check draft app: %w

Error message

failed to check draft app: %w

What it means

Same check as the local variant, but for the old draft directory. If os.Stat(oldDraftDir) fails with anything other than NotExist, RenameLocalApp returns "failed to check draft app: %w" so transient/permission errors are not misread as 'app does not exist'.

Source

Thrown at pkg/waveappstore/waveappstore.go:679

	oldLocalDir := filepath.Join(waveappsDir, AppNSLocal, appName)
	newLocalDir := filepath.Join(waveappsDir, AppNSLocal, newAppName)
	oldDraftDir := filepath.Join(waveappsDir, AppNSDraft, appName)
	newDraftDir := filepath.Join(waveappsDir, AppNSDraft, newAppName)

	// Check if at least one of the apps exists
	localExists := false
	draftExists := false
	if _, err := os.Stat(oldLocalDir); err == nil {
		localExists = true
	} else if !os.IsNotExist(err) {
		return fmt.Errorf("failed to check local app: %w", err)
	}

	if _, err := os.Stat(oldDraftDir); err == nil {
		draftExists = true
	} else if !os.IsNotExist(err) {
		return fmt.Errorf("failed to check draft app: %w", err)
	}

	if !localExists && !draftExists {
		return fmt.Errorf("app '%s' does not exist in local or draft namespace", appName)
	}

	// Check if new app name already exists in either namespace
	if _, err := os.Stat(newLocalDir); err == nil {
		return fmt.Errorf("local app '%s' already exists", newAppName)
	} else if !os.IsNotExist(err) {
		return fmt.Errorf("failed to check if new local app exists: %w", err)
	}

	if _, err := os.Stat(newDraftDir); err == nil {
		return fmt.Errorf("draft app '%s' already exists", newAppName)
	} else if !os.IsNotExist(err) {
		return fmt.Errorf("failed to check if new draft app exists: %w", err)
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Check and fix permissions on ~/waveapps/draft and its contents
  2. Confirm the filesystem is writable/mounted and the disk is healthy
  3. Remount or restart if the filesystem is in a bad state
Defensive patterns

Strategy: try-catch

Validate before calling

draftDir := filepath.Join(wavebase.GetHomeDir(), "waveapps", "draft")
if err := os.Access(draftDir, os.R_OK); err != nil {
    return fmt.Errorf("no read access to draft dir: %w", err)
}

Try / catch

if err := waveappstore.RenameLocalApp(oldName, newName); err != nil {
    if strings.Contains(err.Error(), "failed to check draft app") {
        // surface as an environment/permissions problem, not 'app missing'
        return fmt.Errorf("cannot read draft dir: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: os.Stat(oldDraftDir) returns a non-ENOENT error: unreadable draft directory, permission denied on parents, or I/O failure.

Common situations: Permission changes under ~/waveapps/draft, draft directory owned by another user, disk errors or a read-only filesystem after a crash.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/e6be463a4fe90c19. Report an issue: GitHub.