alibaba/arthas · error · IllegalArgumentException
cursor offset 不允许为负数
Error message
cursor offset 不允许为负数
What it means
Thrown by decodeCursor() in the ViewFile MCP tool when the cursor's offset field is a Number but is negative. Even when supplied via cursor, the resume offset must be >= 0. Surfaced to the caller as 'cursor 解析失败: cursor offset 不允许为负数' (error 98).
Source
Thrown at core/src/main/java/com/taobao/arthas/core/mcp/tool/function/basic1000/ViewFileTool.java:155
}
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);
cursor.put("offset", offset);
String json = JsonParser.toJson(cursor);
return Base64.getUrlEncoder().withoutPadding().encodeToString(json.getBytes(StandardCharsets.UTF_8));
}
private List<Path> loadAllowedRoots() {
String config = System.getenv(ALLOWED_DIRS_ENV);View on GitHub (pinned to 21cf2e9ba5)
Solutions
- Use cursor tokens produced by prior viewfile calls (their offset is always >= 0).
- If constructing manually, set offset to a non-negative value.
Example fix
// before
cursor = base64url({"v":1,"path":"/var/log/app.log","offset":-100})
// after
cursor = base64url({"v":1,"path":"/var/log/app.log","offset":0}) Defensive patterns
Strategy: validation
Validate before calling
long off = ((Number) offset).longValue();
if (off < 0) throw new IllegalArgumentException("offset must be >= 0"); Type guard
static boolean cursorOffsetNonNegative(Map<String,Object> m) {
Object o = m.get("offset");
return o instanceof Number && ((Number) o).longValue() >= 0;
} Try / catch
null
Prevention
- Reuse cursor tokens returned by prior viewfile calls.
- When crafting cursors, set offset to a non-negative value.
When it happens
Trigger: Calling viewfile with a cursor whose decoded offset is < 0, e.g. {"v":1,"path":"/x","offset":-100} encoded as base64url.
Common situations: Tampered or buggy cursor with a negative offset; arithmetic mistake when generating a cursor client-side.
Related errors
AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14).
Data as JSON: /api/errors/76f52ac8f0bf1ffd.
Report an issue: GitHub.