larksuite/cli · error

%s contains invalid characters

Error message

%s contains invalid characters

What it means

ResourceName checks the identifier against the unsafeResourceChars pattern and rejects it if any disallowed character is present. This prevents characters that could alter URL structure or request semantics (e.g. '?', '#') from reaching the endpoint. The message names the offending flag.

Source

Thrown at internal/validate/resource.go:37

// ResourceName validates an API resource identifier (messageId, fileToken, etc.)
// before it is interpolated into a URL path via fmt.Sprintf. It rejects path
// traversal (..), URL metacharacters (?#%), percent-encoded bypasses (%2e%2e),
// control characters, and dangerous Unicode.
//
// Without this check, an input like "../admin" or "?evil=true" in a message ID
// would alter the API endpoint the request is sent to. Works alongside
// EncodePathSegment for defense-in-depth.
func ResourceName(name, flagName string) error {
	if name == "" {
		return fmt.Errorf("%s must not be empty", flagName)
	}
	for _, seg := range strings.Split(name, "/") {
		if seg == ".." {
			return fmt.Errorf("%s must not contain '..' path traversal", flagName)
		}
	}
	if unsafeResourceChars.MatchString(name) {
		return fmt.Errorf("%s contains invalid characters", flagName)
	}
	for _, r := range name {
		if charcheck.IsDangerousUnicode(r) {
			return fmt.Errorf("%s contains dangerous Unicode characters", flagName)
		}
	}
	return nil
}

// EncodePathSegment percent-encodes user input for safe use as a single URL path
// segment (e.g. / → %2F, ? → %3F, # → %23), ensuring the value cannot alter the
// URL routing structure when interpolated into an API path.
//
// This provides defense-in-depth alongside ResourceName: ResourceName rejects known
// dangerous patterns at the input layer, while EncodePathSegment acts as a fallback
// at the concatenation layer — if ResourceName rules are relaxed in the future, or
// if an API path bypasses ResourceName validation (e.g. cmd/service/ generic calls),
// encoding still prevents special characters from being interpreted as path separators

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Trim whitespace and copy only the exact identifier token.
  2. Remove URL fragments/query parts if the ID was copied from a full URL.
  3. Quote variables in shell to avoid stray characters from word splitting.
  4. Use EncodePathSegment if the input legitimately needs URL-unsafe characters.

Example fix

// before
lark-cli im message get --message-id "om_abc?trace=1"
// after
lark-cli im message get --message-id "om_abc"
Defensive patterns

Strategy: validation

Validate before calling

id = strings.TrimSpace(id)
if strings.ContainsAny(id, "?# \t") {
    return fmt.Errorf("id contains URL-significant or whitespace characters")
}

Try / catch

if err := validate.ResourceName(id, "--message-id"); err != nil {
    return fmt.Errorf("clean the id (no query/fragment chars): %w", err)
}

Prevention

When it happens

Trigger: validate.ResourceName receives a name matching unsafeResourceChars — URL-significant characters like '?', '#', or whitespace/control characters in an ID flag.

Common situations: Copying IDs including surrounding URL fragments or query strings, trailing whitespace from copy-paste, spaces introduced by shell word splitting, or injection attempts via '?evil=true'-style input.

Understand the failure class

Related errors


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