larksuite/cli · error

app ID must not be empty

Error message

app ID must not be empty

What it means

ForSubscribe builds a per-app subscribe lock filename from the app ID and rejects an empty app ID up front, because an empty ID would produce an ambiguous shared lock file ("subscribe_.lock") and indicates the caller never configured credentials. It returns a plain descriptive error (no sentinel).

Source

Thrown at internal/lockfile/lockfile.go:35

// safeIDChars strips path-traversal chars from app IDs.
var safeIDChars = regexp.MustCompile(`[^a-zA-Z0-9._-]`)

// ErrHeld signals retryable contention; callers errors.Is to distinguish from real failures.
var ErrHeld = errors.New("lockfile: lock already held")

type LockFile struct {
	path string
	file *os.File
}

func New(path string) *LockFile {
	return &LockFile{path: path}
}

// ForSubscribe sanitises appID against path traversal before forming the lock filename.
func ForSubscribe(appID string) (*LockFile, error) {
	if appID == "" {
		return nil, fmt.Errorf("app ID must not be empty")
	}
	dir := filepath.Join(core.GetConfigDir(), "locks")
	if err := vfs.MkdirAll(dir, 0700); err != nil {
		return nil, fmt.Errorf("create lock dir: %w", err)
	}
	safe := safeIDChars.ReplaceAllString(appID, "_")
	name := filepath.Base(fmt.Sprintf("subscribe_%s.lock", safe))
	path := filepath.Join(dir, name)
	return New(path), nil
}

// TryLock acquires an exclusive non-blocking lock; auto-released on process exit.
func (l *LockFile) TryLock() error {
	if l.file != nil {
		return fmt.Errorf("%w: %s", ErrHeld, l.path)
	}
	f, err := vfs.OpenFile(l.path, os.O_CREATE|os.O_RDWR, 0600)
	if err != nil {

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Run the CLI auth/config setup so app_id is populated in the profile config.
  2. Pass the app ID explicitly via the command's flag/argument.
  3. Check the environment variable feeding the app ID is not unset/empty in your shell or CI.
  4. Validate app ID non-empty in wrapper scripts before invoking the CLI.

Example fix

// before
lock, err := lockfile.ForSubscribe(appID) // appID == ""
// after
if appID == "" {
    return fmt.Errorf("no app configured: run `lark auth` or pass --app-id")
}
lock, err := lockfile.ForSubscribe(appID)
Defensive patterns

Strategy: validation

Validate before calling

if appID == "" {
    return errors.New("no app configured: run `lark auth` or pass --app-id")
}
lock, err := lockfile.ForSubscribe(appID)

Prevention

When it happens

Trigger: Calling lockfile.ForSubscribe("") — e.g. event subscribe executed before any app credentials were configured, or a config/flag that yields an empty app_id string.

Common situations: User ran `lark event subscribe` without ever running auth/config setup; env var or config file has an empty app_id value; a wrapper script passed an unset variable.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/7e9c204269b04500. Report an issue: GitHub.