didi/DoKit · warning · FileNotFoundException
Last path segment is not a resource ID: " + data.uri
Error message
Last path segment is not a resource ID: " + data.uri
What it means
In Utils.getResourceId(Resources, Request), a single-segment android.resource:// URI is interpreted as a raw numeric resource ID (Integer.parseInt of the one segment). If the segment is not a number (e.g. a bare resource name like 'ic_logo'), the NumberFormatException is caught and rethrown as FileNotFoundException('Last path segment is not a resource ID: <uri>') — the single-segment form only accepts IDs, not names.
Source
Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/Utils.java:348
}
static int getResourceId(Resources resources, Request data) throws FileNotFoundException {
if (data.resourceId != 0 || data.uri == null) {
return data.resourceId;
}
String pkg = data.uri.getAuthority();
if (pkg == null) throw new FileNotFoundException("No package provided: " + data.uri);
int id;
List<String> segments = data.uri.getPathSegments();
if (segments == null || segments.isEmpty()) {
throw new FileNotFoundException("No path segments: " + data.uri);
} else if (segments.size() == 1) {
try {
id = Integer.parseInt(segments.get(0));
} catch (NumberFormatException e) {
throw new FileNotFoundException("Last path segment is not a resource ID: " + data.uri);
}
} else if (segments.size() == 2) {
String type = segments.get(0);
String name = segments.get(1);
id = resources.getIdentifier(name, type, pkg);
} else {
throw new FileNotFoundException("More than two path segments: " + data.uri);
}
return id;
}
static Resources getResources(Context context, Request data) throws FileNotFoundException {
if (data.resourceId != 0 || data.uri == null) {
return context.getResources();
}
String pkg = data.uri.getAuthority();View on GitHub (pinned to 626827cddb)
Solutions
- Use the two-segment name form: android.resource://<package>/drawable/ic_logo.
- Or pass the decimal ID as a string: android.resource://<package>/2131099687 (String.valueOf(resId)).
- Best for local resources: pass the int directly via picasso.load(resId).
Example fix
// before
Uri uri = Uri.parse("android.resource://com.example.app/ic_logo"); // name, not ID
picasso.load(uri).into(imageView);
// after
Uri uri = Uri.parse("android.resource://com.example.app/drawable/ic_logo");
picasso.load(uri).into(imageView); Defensive patterns
Strategy: validation
Validate before calling
Uri resourceUri(Context ctx, String type, String name) {
return new Uri.Builder().scheme("android.resource")
.authority(ctx.getPackageName())
.appendPath(type).appendPath(name).build(); // 2-segment name form
} Try / catch
Catch in error callback; the message includes the URI so mis-built segments are easy to spot in logs.
Prevention
- Single-segment form accepts decimal IDs only; names need the two-segment form.
- Pass String.valueOf(resId) when using the short form.
- Validate one-segment URIs with a numeric regex before loading.
When it happens
Trigger: Passing android.resource://com.example.app/ic_logo — a one-segment path containing a resource NAME instead of a number; passing a numeric string with whitespace or a '#'/hex prefix.
Common situations: Assuming the short form accepts names like the two-segment form does; passing Integer.toHexString(resId) or a formatted string ('res 2131099687') as the segment.
Related errors
- More than two path segments: " + data.uri
- No package provided: " + data.uri
- No path segments: " + data.uri
- Unrecognized type of request: " + request
- Invalid uri: <uri>
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/c63c9bb6fdb451c5.
Report an issue: GitHub.