github/copilot-sdk · error · IllegalArgumentException
BuiltinPluginDirectories must contain only absolute paths…
Error message
BuiltinPluginDirectories must contain only absolute paths: + path
What it means
CopilotClientOptions.setBuiltinPluginDirectories validates that every supplied Path is absolute before storing it. A relative path would resolve against an unpredictable working directory at client start, so the builder rejects the whole list with IllegalArgumentException naming the offending path.
Solutions
- Resolve relative paths against a known base before passing them: path.toAbsolutePath() (or base.resolve(path)).
- Check each path with Path.isAbsolute() in your config loader and fail/normalize early.
- Anchor config values to a documented base directory (e.g. install dir or $HOME) and document it.
- If you intend an empty set, pass an empty collection or null — the builder supports clearing the list.
Example fix
// before
builder.setBuiltinPluginDirectories(List.of(Path.of("plugins/builtin")));
// after
Path dir = Path.of("plugins/builtin").toAbsolutePath();
builder.setBuiltinPluginDirectories(List.of(dir)); Defensive patterns
Strategy: validation
Validate before calling
List<Path> safe = paths.stream()
.peek(p -> Objects.requireNonNull(p, "plugin dir must not be null"))
.map(Path::toAbsolutePath)
.collect(Collectors.toList());
options.setBuiltinPluginDirectories(safe); Type guard
static boolean allAbsolute(List<Path> paths) {
return paths != null && paths.stream().allMatch(Objects::nonNull) &&
paths.stream().allMatch(Path::isAbsolute);
} Try / catch
try {
builder.setBuiltinPluginDirectories(paths);
} catch (IllegalArgumentException e) {
Path bad = Path.of(e.getMessage().substring(e.getMessage().lastIndexOf(': ') + 2));
builder.setBuiltinPluginDirectories(List.of(bad.toAbsolutePath()));
} Prevention
- Always call toAbsolutePath() on paths read from config files
- Resolve plugin dirs against a documented base directory
- Log the working directory at startup to debug relative-path confusion
- Validate configured paths once at config load, before client construction
When it happens
Trigger: Calling setBuiltinPluginDirectories with a list containing at least one relative path, e.g. Path.of("plugins/builtin") or Paths.get("./ext"), or paths built from user-relative config strings.
Common situations: Config files storing plugin directories relative to a project root; building Paths from CLI args without resolution; environment-dependent working directories making relative paths behave differently across machines.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- CliUrl is mutually exclusive with CliPath
- TcpConnectionToken must be a non-empty string
- Invalid value ' '. Expected 'inprocess', 'stdio', or unset.
- Unknown AgentMode value: + value
- Unknown AskUserVariant value: + value
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/8b964561076f0473.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/rpc/CopilotClientOptions.java:153
/**
* Sets trusted plugin directories bundled by the host. Every path must be
* absolute. When non-empty, the complete set is registered during startup
* before sessions can be created.
*
* @param paths
* absolute plugin directory paths, or {@code null}/empty to disable
* @return this options instance for method chaining
*/
public CopilotClientOptions setBuiltinPluginDirectories(List<Path> paths) {
if (paths == null || paths.isEmpty()) {
this.builtinPluginDirectories = null;
return this;
}
for (Path path : paths) {
Objects.requireNonNull(path, "builtin plugin directory path must not be null");
if (!path.isAbsolute()) {
throw new IllegalArgumentException(
"BuiltinPluginDirectories must contain only absolute paths: " + path);
}
}
this.builtinPluginDirectories = new ArrayList<>(paths);
return this;
}
/**
* Gets the extra CLI arguments.
* <p>
* Returns a shallow copy of the internal array, or {@code null} if no arguments
* have been set.
*
* @return a copy of the extra arguments, or {@code null}
*/
public String[] getCliArgs() {
return cliArgs != null ? Arrays.copyOf(cliArgs, cliArgs.length) : null;
}View on GitHub (pinned to cd8cf15dc3)