wavetermdev/waveterm · error

invalid app name: must match pattern [a-zA-Z0-9_-]+

Error message

invalid app name: must match pattern [a-zA-Z0-9_-]+

What it means

The app name segment of an appId must match ^[a-zA-Z0-9_-]+$ — only ASCII letters, digits, underscores, and hyphens. This error means the name contains other characters (dots, spaces, slashes, unicode) making it unsafe as a directory name under ~/.waveapps.

Source

Thrown at pkg/waveappstore/waveappstore.go:75

	return appNS, appName, nil
}

func ValidateAppId(appId string) error {
	appNS, appName, err := ParseAppId(appId)
	if err != nil {
		return err
	}
	if len(appNS) > MaxNamespaceLen {
		return fmt.Errorf("namespace too long: max %d characters", MaxNamespaceLen)
	}
	if len(appName) > MaxAppNameLen {
		return fmt.Errorf("app name too long: max %d characters", MaxAppNameLen)
	}
	if !namespaceRegex.MatchString(appNS) {
		return fmt.Errorf("invalid namespace: must match pattern @?[a-z0-9-]+")
	}
	if !appNameRegex.MatchString(appName) {
		return fmt.Errorf("invalid app name: must match pattern [a-zA-Z0-9_-]+")
	}
	return nil
}

func GetAppDir(appId string) (string, error) {
	if err := ValidateAppId(appId); err != nil {
		return "", err
	}
	appNS, appName, _ := ParseAppId(appId)
	homeDir := wavebase.GetHomeDir()
	return filepath.Join(homeDir, "waveapps", appNS, appName), nil
}

func copyDir(src, dst string) error {
	if err := os.RemoveAll(dst); err != nil && !os.IsNotExist(err) {
		return fmt.Errorf("failed to remove existing directory: %w", err)
	}
	if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Sanitize the name: replace '.' and spaces with '-' or '_', and transliterate/strip non-ASCII characters.
  2. Use a slug function before composing the appId (e.g. strings.NewReplacer(".", "-", " ", "-")).
  3. Pre-validate in UI with pattern ^[a-zA-Z0-9_-]+$ and reject at input time.
  4. Use "myapp-1-0" style version suffixes instead of dotted versions.

Example fix

// before
appId := "local/myapp-1.0" // dot not allowed in app name
err := waveappstore.ValidateAppId(appId)
// after
appId := "local/myapp-1-0" // matches ^[a-zA-Z0-9_-]+$
err := waveappstore.ValidateAppId(appId)
Defensive patterns

Strategy: validation

Validate before calling

var appNamePattern = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)
func namePatternOK(appId string) bool {
    _, name, err := waveappstore.ParseAppId(appId)
    return err == nil && appNamePattern.MatchString(name)
}

Type guard

func isValidAppName(name string) bool {
    return regexp.MustCompile(`^[a-zA-Z0-9_-]+$`).MatchString(name)
}

Try / catch

if err := waveappstore.ValidateAppId(appId); err != nil {
    if strings.Contains(err.Error(), "invalid app name") {
        return fmt.Errorf("app name may only contain letters, digits, '_' and '-': %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ValidateAppId (directly or via GetAppDir, PublishDraft, RevertDraft, MakeDraftFromLocal, DeleteApp, WriteAppFile) with app names like "my.app", "my app", "マイアプリ", or "app v2" after the namespace slash.

Common situations: Deriving app names from file names or titles that include dots and spaces; localized/unicode app titles used verbatim as ids; version suffixes like "myapp-1.0" containing a dot.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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