wavetermdev/waveterm · error

invalid appId format: must be namespace/name

Error message

invalid appId format: must be namespace/name

What it means

ParseAppId splits a wave appId string on '/' and requires exactly two non-empty segments: namespace and name. This error is returned when the appId does not contain exactly one slash-separated pair — e.g. zero slashes or more than one. It guards the path layout used on disk (~/.waveapps/<ns>/<name>) and downstream validation.

Source

Thrown at pkg/waveappstore/waveappstore.go:50

var (
	namespaceRegex = regexp.MustCompile(`^@?[a-z0-9-]+$`)
	appNameRegex   = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)
)

type FileData struct {
	Contents []byte
	ModTs    int64
}

func MakeAppId(appNS string, appName string) string {
	return appNS + "/" + appName
}

func ParseAppId(appId string) (appNS string, appName string, err error) {
	parts := strings.Split(appId, "/")
	if len(parts) != 2 {
		return "", "", fmt.Errorf("invalid appId format: must be namespace/name")
	}
	appNS = parts[0]
	appName = parts[1]
	if appNS == "" || appName == "" {
		return "", "", fmt.Errorf("invalid appId: namespace and name cannot be empty")
	}
	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 {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Format the appId as namespace/name with exactly one slash, e.g. "local/myapp" or "@team/myapp".
  2. Use waveappstore.MakeAppId(ns, name) to construct the id instead of string concatenation.
  3. Call waveappstore.ValidateAppId(appId) before use to get precise feedback.
  4. Trim stray '/' characters from user/config-supplied ids.

Example fix

// before
appId := "myapp"                       // missing namespace
err := waveappstore.ValidateAppId(appId) // invalid appId format
// after
appId := waveappstore.MakeAppId("local", "myapp") // "local/myapp"
err := waveappstore.ValidateAppId(appId)
Defensive patterns

Strategy: validation

Validate before calling

func checkAppIdFormat(appId string) error {
    parts := strings.Split(appId, "/")
    if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
        return fmt.Errorf("appId must be namespace/name with both parts non-empty")
    }
    return nil
}
if err := checkAppIdFormat(appId); err != nil { /* handle before calling the library */ }

Type guard

func isValidAppIdShape(appId string) bool {
    parts := strings.Split(appId, "/")
    return len(parts) == 2 && parts[0] != "" && parts[1] != ""
}

Try / catch

if err := waveappstore.ValidateAppId(appId); err != nil {
    if strings.Contains(err.Error(), "invalid appId format") {
        fmt.Fprintf(os.Stderr, "usage: appId must look like 'local/myapp', got %q\n", appId)
        os.Exit(2)
    }
    return err
}

Prevention

When it happens

Trigger: Passing an appId with no '/' (e.g. "myapp"), multiple slashes (e.g. "@team/sub/app"), a trailing slash ("local/app/"), or an empty string to ParseAppId, ValidateAppId, GetAppDir, PublishDraft, RevertDraft, MakeDraftFromLocal, or buildAndRun.

Common situations: Hard-coding just the app name and forgetting the namespace prefix; concatenating a namespaced identifier that itself contains a slash; reading an appId from config/CLI with an accidental trailing slash; confusing MakeAppId(ns, name) output with the name alone.

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