{"record":{"id":"f40aa17064e18e7d","repo":"google/ExoPlayer","slug":"priority-too-low-priority-d-highest-d","errorCode":null,"errorMessage":"Priority too low [priority=%d, highest=%d]","messagePattern":"Priority too low \\[priority=(.+?), highest=(.+?)\\]","errorType":"exception","errorClass":"PriorityTaskManager.PriorityTooLowException","httpStatus":null,"severity":"warning","filePath":"library/common/src/main/java/com/google/android/exoplayer2/util/PriorityTaskManager.java","lineNumber":106,"sourceCode":"   * @param priority The priority of the task.\n   * @return Whether the task is allowed to proceed.\n   */\n  public boolean proceedNonBlocking(int priority) {\n    synchronized (lock) {\n      return highestPriority == priority;\n    }\n  }\n\n  /**\n   * A throwing variant of {@link #proceed(int)}.\n   *\n   * @param priority The priority of the task.\n   * @throws PriorityTooLowException If the task is not allowed to proceed.\n   */\n  public void proceedOrThrow(int priority) throws PriorityTooLowException {\n    synchronized (lock) {\n      if (highestPriority != priority) {\n        throw new PriorityTooLowException(priority, highestPriority);\n      }\n    }\n  }\n\n  /**\n   * Unregister a task.\n   *\n   * @param priority The priority of the task.\n   */\n  public void remove(int priority) {\n    synchronized (lock) {\n      queue.remove(priority);\n      highestPriority = queue.isEmpty() ? Integer.MIN_VALUE : Util.castNonNull(queue.peek());\n      lock.notifyAll();\n    }\n  }\n}\n","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/library/common/src/main/java/com/google/android/exoplayer2/util/PriorityTaskManager.java#L88-L124","documentation":"PriorityTaskManager.proceedOrThrow(priority) throws PriorityTooLowException when the caller's priority does not exactly equal the manager's current highest_priority — meaning some other registered task is running at a higher priority and lower-priority work must not proceed. ExoPlayer uses this for codec/derasterizer vs network/download contention: network tasks call proceedOrThrow in a loop, backing off until their priority becomes the highest. It extends IOException, signaling a transient, retryable condition rather than a hard failure.","triggerScenarios":"A task registered at priority N calls proceedOrThrow(N) while playback (registered higher, e.g. C.PRIORITY_PLAYBACK) holds highest_priority; typical flow is PriorityTaskManager.proceed(N) which blocks, but code paths like CacheDataSource/HttpDataSource interruption handling call proceedOrThrow and expect PriorityTooLowException to pause downloading.","commonSituations":"Custom DownloadManager or CacheDataSource integrations where download priority (C.PRIORITY_BACKGROUND) is below active playback priority; multiple simultaneous streams re-prioritizing; calling proceedOrThrow while another thread's add() raised highest_priority between your add() and proceedOrThrow().","solutions":["Retry or block instead of failing: catch PriorityTooLowException and either wait/backoff-retry, or simply use proceed(priority) which blocks until the priority is highest — that is the intended API for long tasks","Ensure priorities are consistent with registration: proceed/proceedOrThrow must be called with the same priority value the task registered with via add(priority)","Re-check ordering around cancelation: always call remove(priority) in finally so highest_priority falls and other tasks can proceed","For custom task types, register with C.PRIORITY_* constants that order sensibly vs playback so downloads yield but still run when idle"],"exampleFix":"// before\nmanager.proceedOrThrow(C.PRIORITY_BACKGROUND); // throws while playback active\n// after\nmanager.proceed(C.PRIORITY_BACKGROUND); // blocks until allowed\ntry {\n  // task body\n} finally {\n  manager.remove(C.PRIORITY_BACKGROUND);\n}","handlingStrategy":"retry","validationCode":"if (!manager.isRegisteredPriorityCurrent(priority)) { /* library-dependent; in practice: catch and retry */ }","typeGuard":null,"tryCatchPattern":"while (true) {\n  try { manager.proceedOrThrow(priority); break; }\n  catch (PriorityTooLowException e) {\n    // back off and retry, or switch to manager.proceed(priority) which blocks\n  }\n}","preventionTips":["Prefer proceed(priority) (blocking) for long tasks; proceedOrThrow is for cooperative loops that yield","Always pair add(priority) ... finally remove(priority)","Register with the C.PRIORITY_* constants so ordering vs playback is deterministic"],"tags":["concurrency","priority","io","downloads"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}