theonedev/onedev · critical · ExplicitException

Base resource mapper should be used

Error message

Base resource mapper should be used

What it means

BaseUrlMapper enforces that any added resource request mapper extend BaseResourceMapper. Adding a plain Wicket ResourceMapper violates the framework's URL/mounting convention and throws an ExplicitException at startup.

Source

Thrown at server-core/src/main/java/io/onedev/server/web/mapper/BaseUrlMapper.java:216

import io.onedev.server.web.resource.AgentLibResourceReference;
import io.onedev.server.web.resource.AgentLogResourceReference;
import io.onedev.server.web.resource.AgentResourceReference;
import io.onedev.server.web.resource.ArchiveResourceReference;
import io.onedev.server.web.resource.ArtifactResourceReference;
import io.onedev.server.web.resource.AttachmentResourceReference;
import io.onedev.server.web.resource.BuildLogResourceReference;
import io.onedev.server.web.resource.PatchResourceReference;
import io.onedev.server.web.resource.RawBlobResourceReference;
import io.onedev.server.web.resource.ServerLogResourceReference;
import io.onedev.server.web.resource.SiteFileResourceReference;
import io.onedev.server.web.resource.SpriteResourceReference;

public class BaseUrlMapper extends CompoundRequestMapper {

	@Override
	public CompoundRequestMapper add(IRequestMapper mapper) {
		if (mapper instanceof ResourceMapper && !(mapper instanceof BaseResourceMapper))
			throw new ExplicitException("Base resource mapper should be used");
		return super.add(mapper);
	}

	public BaseUrlMapper(WebApplication app) {
		add(new BasePageMapper("~init", ServerInitPage.class));
		add(new BasePageMapper("~loading", BrowserInfoPage.class));
		addProjectPages();
		add(new BasePageMapper("~issues", IssueListPage.class));
		add(new BasePageMapper("~pulls", PullRequestListPage.class));
		add(new BasePageMapper("~builds", BuildListPage.class));
		add(new BasePageMapper("~packages", PackListPage.class));
		add(new BasePageMapper("~workspaces", WorkspaceListPage.class));
		addAdministrationPages();
		addUserPages();
		addMyPages();
		addSecurityPages();
		addResources();
		addHelpPages();

View on GitHub (pinned to d44925c47c)

Solutions

  1. Change the mapper to extend BaseResourceMapper and register it via its contribute() convention.
  2. Upgrade the offending plugin to a OneDev-compatible version.
  3. Remove the custom ResourceMapper registration.

Example fix

// before
add(new ResourceMapper("/static", SomeResource.class));
// after
add(new BaseResourceMapper("/static", SomeResourceReference.class));
Defensive patterns

Strategy: validation

Validate before calling

if (!(mapper instanceof BaseResourceMapper))
    throw new IllegalStateException("Use BaseResourceMapper with BaseUrlMapper");

Type guard

function isAllowedMapper(m){ return m instanceof BaseResourceMapper; }

Try / catch

try {
    baseUrlMapper.add(mapper);
} catch (ExplicitException e) {
    log.error("Mapper rejected: wrap it in BaseResourceMapper", e);
}

Prevention

When it happens

Trigger: Plugin or customization code calls baseUrlMapper.add(new ResourceMapper(...)) with a ResourceMapper that is not a BaseResourceMapper, during application initialization.

Common situations: Third-party plugin incompatible with the OneDev version; custom code copied from stock Wicket examples; refactor where a mapper no longer extends BaseResourceMapper.

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


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/1571067b8b78d77b. Report an issue: GitHub.