conductor-oss/conductor · error · IllegalArgumentException

skillRef is required

Error message

skillRef is required

What it means

Thrown by resolveRawConfig() when the skillRef argument is null. resolveRawConfig is called internally by AgentService (line 1222) when starting an agent from a skillRef, and requires a non-null map containing at least a 'name' key. A null skillRef means no skill was referenced at all.

Source

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

                        .path(cleanPath)
                        .contentType(contentType(cleanPath))
                        .size(data.length)
                        .binary(binary)
                        .content(binary ? null : new String(data, StandardCharsets.UTF_8))
                        .contentBase64(binary ? Base64.getEncoder().encodeToString(data) : null)
                        .build();
            }
            throw new IllegalArgumentException("Skill file not found: " + cleanPath);
        } catch (IOException e) {
            throw new IllegalStateException("Failed to read skill file: " + e.getMessage(), e);
        }
    }

    @SuppressWarnings("unchecked")
    public Map<String, Object> resolveRawConfig(Map<String, Object> skillRef) {
        requireSkillStorage();
        if (skillRef == null) {
            throw new IllegalArgumentException("skillRef is required");
        }
        String name = requiredString(skillRef, "name");
        String version = stringValue(skillRef.get("version"));
        SkillDetail detail = get(name, version);
        Map<String, Object> rawConfig = rawConfigForDetail(detail, new HashSet<>());
        Object model = skillRef.get("model");
        if (model instanceof String s && !s.isBlank()) {
            rawConfig.put("model", s);
        }
        Object agentModels = skillRef.get("agentModels");
        if (agentModels instanceof Map<?, ?> map && !map.isEmpty()) {
            rawConfig.put("agentModels", MAPPER.convertValue(map, Map.class));
        }
        Object workspace = skillRef.get("workspace");
        if (workspace instanceof Map<?, ?> map && !map.isEmpty()) {
            rawConfig.put("workspace", MAPPER.convertValue(map, Map.class));
        }
        Object params = skillRef.get("params");

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Populate skillRef with at least {"name":"<skill-name>"} in the AgentStartRequest.
  2. Add a null/empty check on skillRef on the client before starting the agent.
  3. If starting without a skill is valid, use a different framework and do not call the skill path.

Example fix

// before
AgentStartRequest.builder().framework("skill").skillRef(null).build();
// after
AgentStartRequest.builder()
    .framework("skill")
    .skillRef(Map.of("name","foo","version","1.0.0"))
    .build();
Defensive patterns

Strategy: validation

Validate before calling

// Before starting an agent from a skill, assert skillRef is present and named
if (request.getSkillRef() == null || !(request.getSkillRef().get("name") instanceof String s && !s.isBlank())) {
    throw new IllegalArgumentException("skillRef.name is required for framework=skill");
}

Type guard

static boolean hasValidSkillRef(AgentStartRequest r) {
    Map<String,Object> ref = r.getSkillRef();
    return ref != null && ref.get("name") instanceof String s && !s.isBlank();
}

Prevention

When it happens

Trigger: AgentStartRequest submitted with framework=skill but skillRef=null (or omitted), routed to AgentService which calls resolveRawConfig(null). Also a direct service caller passing null.

Common situations: Client builds an agent start request and forgets to populate skillRef; a workflow definition references a skill but the skillRef field is left empty due to a templating error; JSON deserialization yielding null when the field is absent and not defaulted.

Related errors


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