alibaba/arthas · error · IllegalArgumentException
cursor 缺少 path
Error message
cursor 缺少 path
What it means
Thrown by decodeCursor() in the ViewFile MCP tool when a cursor token is decoded (base64url -> JSON) but the resulting map has no 'path' field, or 'path' is not a non-empty String. The cursor encodes a path and offset to resume reading; a missing path makes the cursor unusable.
Source
Thrown at core/src/main/java/com/taobao/arthas/core/mcp/tool/function/basic1000/ViewFileTool.java:148
private final String path;
private final long offset;
private CursorValue(String path, long offset) {
this.path = path;
this.offset = offset;
}
}
private CursorValue decodeCursor(String cursor) {
try {
byte[] jsonBytes = Base64.getUrlDecoder().decode(cursor);
String json = new String(jsonBytes, StandardCharsets.UTF_8);
Map<String, Object> map = JsonParser.fromJson(json, new TypeReference<Map<String, Object>>() {});
Object pathObj = map.get("path");
Object offsetObj = map.get("offset");
if (!(pathObj instanceof String) || ((String) pathObj).trim().isEmpty()) {
throw new IllegalArgumentException("cursor 缺少 path");
}
if (!(offsetObj instanceof Number)) {
throw new IllegalArgumentException("cursor 缺少 offset");
}
long offset = ((Number) offsetObj).longValue();
if (offset < 0) {
throw new IllegalArgumentException("cursor offset 不允许为负数");
}
return new CursorValue(((String) pathObj).trim(), offset);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("cursor 解析失败: " + e.getMessage(), e);
}
}
private String encodeCursor(String path, long offset) {
Map<String, Object> cursor = new LinkedHashMap<>();
cursor.put("v", 1);
cursor.put("path", path);View on GitHub (pinned to 21cf2e9ba5)
Solutions
- Use only cursor tokens produced by a previous successful viewfile call (they always include path).
- If constructing a cursor manually, ensure JSON has a non-empty string "path" field, e.g. {"v":1,"path":"/var/log/app.log","offset":0}.
Example fix
// before
cursor = base64url({"v":1,"offset":0})
// after
cursor = base64url({"v":1,"path":"/var/log/app.log","offset":0}) Defensive patterns
Strategy: validation
Validate before calling
// When building a cursor, always include a non-empty path
Map<String,Object> c = new LinkedHashMap<>();
c.put("v", 1);
c.put("path", Objects.requireNonNull(path, "path"));
if (path == null || path.trim().isEmpty()) throw new IllegalArgumentException("path required");
c.put("offset", offset); Type guard
static boolean cursorHasValidPath(Map<String,Object> m) {
Object p = m.get("path");
return p instanceof String && !((String) p).trim().isEmpty();
} Try / catch
null
Prevention
- Reuse cursor tokens returned by prior viewfile calls.
- When crafting cursors, always include a non-empty string path.
When it happens
Trigger: Calling viewfile with a cursor whose decoded JSON omits 'path' (e.g. {"v":1,"offset":0}) or has path=""/non-string. Ultimately surfaced as 'cursor 解析失败: cursor 缺少 path' (error 98) because decodeCursor wraps it.
Common situations: Hand-crafting or stale cursor token missing the path field; truncated/corrupted cursor; client bug constructing the cursor JSON.
Related errors
AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14).
Data as JSON: /api/errors/ccf63a509d298ecc.
Report an issue: GitHub.