conductor-oss/conductor · error · IllegalArgumentException

Invalid skill version '{version}'. Use 1-128 characters: let

Error message

Invalid skill version '{version}'. Use 1-128 characters: letters, numbers, '.', '_', '+', or '-'.

What it means

validateVersion throws when the version string does not fully match `[A-Za-z0-9._+-]{1,128}`. SemVer-style versions (`1.0.0`, `2.5.0-beta+build.7`) are accepted because dots, plus, and hyphen are allowed; rejected versions contain spaces, slashes, colons, or other punctuation.

Source

Thrown at agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/service/SkillRegistryService.java:941

            if (part.isBlank() || ".".equals(part) || "..".equals(part)) {
                throw new IllegalArgumentException("Invalid skill package path: " + name);
            }
        }
        return normalized;
    }

    private void validateSkillName(String name) {
        if (!SKILL_NAME_PATTERN.matcher(name).matches()) {
            throw new IllegalArgumentException(
                    "Invalid skill name '"
                            + name
                            + "'. Use 1-128 characters: letters, numbers, '.', '_' or '-'.");
        }
    }

    private void validateVersion(String version) {
        if (!VERSION_PATTERN.matcher(version).matches()) {
            throw new IllegalArgumentException(
                    "Invalid skill version '"
                            + version
                            + "'. Use 1-128 characters: letters, numbers, '.', '_', '+', or '-'.");
        }
    }

    private String sha256Hex(byte[] bytes) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            return hex(digest.digest(bytes));
        } catch (Exception e) {
            throw new IllegalStateException("SHA-256 digest is unavailable", e);
        }
    }

    private static String hex(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Use a SemVer string: `1.0.0`, `2.0.0-rc1`, `1.5.2+build.42`.
  2. Move descriptive labels into a separate `label`/`description` field.
  3. Trim leading `v` only if your tooling rejects it (the pattern allows `v`, so usually unnecessary).

Example fix

// before
version: "1.0.0 (stable)"
// after
version: "1.0.0"
label: "stable"
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern SKILL_VER = Pattern.compile("[A-Za-z0-9._+-]{1,128}");
boolean isValidVersion(String v) {
    return v != null && SKILL_VER.matcher(v).matches();
}

Type guard

boolean isSkillVersion(String s) {
    return s != null && Pattern.compile("[A-Za-z0-9._+-]{1,128}").matcher(s).matches();
}

Try / catch

try { skillRegistry.validateVersion(version); }
catch (IllegalArgumentException e) { return badRequest(e.getMessage()); }

Prevention

When it happens

Trigger: Publishing a skill whose `version` is `1.0.0 (latest)`, `v1/2`, `1.0.0^`, or longer than 128 chars. The VERSION_PATTERN.matcher().matches() returns false.

Common situations: Author added a friendly suffix in parens; included a caret from npm-style ranges; pasted a build URL into the version field.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/023e103e89f2901b. Report an issue: GitHub.