theonedev/onedev · error · ExplicitException
Unable to find job:
Error message
Unable to find job:
What it means
JobIndex.of(pipeline, job) searches every column of the pipeline's job matrix for the given Job instance using equals(). If the job is not present in any column it throws an ExplicitException. It is an internal invariant: only jobs belonging to the pipeline are expected to be indexed.
Source
Thrown at server-core/src/main/java/io/onedev/server/web/component/pipeline/JobIndex.java:42
}
public int getColumn() {
return column;
}
public int getRow() {
return row;
}
public static JobIndex of(List<List<Job>> pipeline, Job job) {
for (int columnIndex = 0; columnIndex < pipeline.size(); columnIndex++) {
List<Job> column = pipeline.get(columnIndex);
for (int rowIndex = 0; rowIndex < column.size(); rowIndex++) {
if (column.get(rowIndex).equals(job))
return new JobIndex(columnIndex, rowIndex);
}
}
throw new ExplicitException("Unable to find job: " + job.getName());
}
public Job getJob(List<List<Job>> pipeline) {
return pipeline.get(column).get(row);
}
public String toJson() {
try {
return OneDev.getInstance(ObjectMapper.class).writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return column + "-" + row;
}View on GitHub (pinned to d44925c47c)
Solutions
- Ensure the Job instance passed to of() comes from the same pipeline object being searched.
- Compare by job name/identifier if instances may come from different persistence contexts.
- Check whether the build spec was recently edited and the job was removed or renamed.
- Reload the pipeline from the current build spec before indexing the job.
Example fix
// before
JobIndex index = JobIndex.of(pipeline, otherPipelineJob);
// after
if (pipeline.getJobs().stream().anyMatch(j -> j.equals(job))) {
JobIndex index = JobIndex.of(pipeline, job);
} Defensive patterns
Strategy: validation
Validate before calling
boolean present = pipeline.stream().flatMap(List::stream).anyMatch(j -> j.equals(job));
if (!present) throw new IllegalArgumentException("job not in pipeline"); Type guard
boolean jobInPipeline = pipeline.stream().flatMap(List::stream).anyMatch(job::equals);
Try / catch
try { return JobIndex.of(pipeline, job); } catch (ExplicitException e) { throw new IllegalArgumentException("Job '" + job.getName() + "' does not belong to the pipeline", e); } Prevention
- Only pass Job instances sourced from the same pipeline object
- Compare jobs by stable identity/name when crossing persistence boundaries
- Re-resolve the pipeline after build spec edits
When it happens
Trigger: Calling JobIndex.of(pipeline, job) with a Job instance that is not contained (by equals) in any list of the pipeline matrix, e.g. a job from a different pipeline or a stale/detached entity instance.
Common situations: Passing a Job loaded from a different session so equals() fails against the pipeline's in-memory jobs; referencing a job that was removed from the pipeline in a build spec edit; a plugin constructing a JobIndex for a job that never existed in this pipeline.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Non-existent issue specified in recipient address:
- Non-existent pull request specified in recipient address:
- Unable to find build #{0} in project {1}
- Unable to find build #{0} in project {1}
- Workspace not found
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/694a9cb95e8ebff4.
Report an issue: GitHub.