theonedev/onedev · error · ExplicitException
Base resource mapper should be used
Error message
Base resource mapper should be used
What it means
WebApplication.mount() overrides Wicket's mount to require that any IRequestMapper of type ResourceMapper also extends OneDev's BaseResourceMapper. BaseResourceMapper adds OneDev-specific handling (canonical URL generation etc.), so a raw Wicket ResourceMapper would break resource URL handling. A plain ResourceMapper passed to mount() triggers this ExplicitException.
Source
Thrown at server-core/src/main/java/io/onedev/server/web/WebApplication.java:276
setRequestCycleProvider(context -> new RequestCycle(context) {
@Override
protected UrlRenderer newUrlRenderer() {
return new AbsoluteUrlRenderer(getRequest());
}
});
mount(new BaseUrlMapper(this));
for (WebApplicationConfigurator configurator: applicationConfigurators)
configurator.configure(this);
}
@Override
public void mount(IRequestMapper mapper) {
if (mapper instanceof ResourceMapper && !(mapper instanceof BaseResourceMapper))
throw new ExplicitException("Base resource mapper should be used");
super.mount(mapper);
}
@Override
public final IProvider<IExceptionMapper> getExceptionMapperProvider() {
return new IProvider<>() {
@Override
public IExceptionMapper get() {
return new DefaultExceptionMapper() {
@Override
protected IRequestHandler mapExpectedExceptions(Exception e, Application application) {
RequestCycle requestCycle = RequestCycle.get();
boolean isAjax = ((WebRequest) requestCycle.getRequest()).isAjax();
if (isAjax && (e instanceof ListenerInvocationNotAllowedException || e instanceof ComponentNotFoundException || e instanceof InvalidBehaviorIdException))
return EmptyAjaxRequestHandler.getInstance();
View on GitHub (pinned to d44925c47c)
Solutions
- Use OneDev's BaseResourceMapper (or a subclass) instead of a raw ResourceMapper when mounting.
- If you need custom mapper behavior, extend BaseResourceMapper and override only what you need.
- Check which init contributor mounts the mapper and replace it with the OneDev base class.
Example fix
// before
app.mount(new ResourceMapper("/assets", new MyResourceReference()));
// after
app.mount(new BaseResourceMapper("/assets", new MyResourceReference())); Defensive patterns
Strategy: validation
Validate before calling
if (mapper instanceof ResourceMapper && !(mapper instanceof BaseResourceMapper)) {
throw new IllegalStateException("Use BaseResourceMapper instead of raw ResourceMapper");
}
application.mount(mapper); Type guard
static boolean isMountable(IRequestMapper m) {
return !(m instanceof ResourceMapper) || m instanceof BaseResourceMapper;
} Prevention
- Use BaseResourceMapper for all resource mapper mounting in OneDev plugins.
- Do not copy mapper mounting code from generic Wicket tutorials verbatim.
- Smoke-test plugin init locally with ./dev.sh run to catch mount failures early.
When it happens
Trigger: Calling application.mount(new ResourceMapper(...)) (or any ResourceMapper subclass that is not a BaseResourceMapper) during application/plugin initialization.
Common situations: Plugin authors following generic Wicket tutorials for mounting resource mappers; copying mapper code from a non-OneDev Wicket project into an OneDev initContributor.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Page classes should extend from BasePage.
- Invalid date range, expecting "yyyy-MM-dd to yyyy-MM-dd"
- Path '${mountPath}' should be mounted to a svg sprite resour
- Unable to find svg sprite resource mounted at: ${mountPath}
- Invalid number: ${token}
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/55403369408c19a5.
Report an issue: GitHub.