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
- Populate skillRef with at least {"name":"<skill-name>"} in the AgentStartRequest.
- Add a null/empty check on skillRef on the client before starting the agent.
- 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
- On the client, require skillRef.name whenever framework=skill is selected.
- Add a request-level validator for AgentStartRequest that fails fast on a null skillRef.
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
- Skill manifest name '{manifestName}' does not match package
- Skill {name} version {version} already exists with a differe
- File path is required
- Skill manifest is required
- Invalid skill manifest JSON: {e.getMessage()}
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/b653af7c4dc3bb50.
Report an issue: GitHub.