{"record":{"id":"8384ec3d36f6b4a3","repo":"airbnb/lottie-android","slug":"a-task-may-only-be-set-once","errorCode":null,"errorMessage":"A task may only be set once.","messagePattern":"A task may only be set once\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"lottie/src/main/java/com/airbnb/lottie/LottieTask.java","lineNumber":95,"sourceCode":"  /**\n   * runNow is only used for testing.\n   */\n  @RestrictTo(RestrictTo.Scope.LIBRARY) LottieTask(Looper uiLooper, Callable<LottieResult<T>> runnable, boolean runNow) {\n    uiHandler = new Handler(uiLooper);\n    if (runNow) {\n      try {\n        setResult(runnable.call());\n      } catch (Throwable e) {\n        setResult(new LottieResult<>(e));\n      }\n    } else {\n      EXECUTOR.execute(new LottieFutureTask<T>(this, runnable));\n    }\n  }\n\n  private void setResult(@Nullable LottieResult<T> result) {\n    if (this.result != null) {\n      throw new IllegalStateException(\"A task may only be set once.\");\n    }\n    this.result = result;\n    notifyListeners();\n  }\n\n  /**\n   * Add a task listener. If the task has completed, the listener will be called synchronously.\n   *\n   * @return the task for call chaining.\n   */\n  public synchronized LottieTask<T> addListener(LottieListener<T> listener) {\n    LottieResult<T> result = this.result;\n    if (result != null && result.getValue() != null) {\n      listener.onResult(result.getValue());\n    }\n\n    successListeners.add(listener);\n    return this;","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/airbnb/lottie-android/blob/05ea92e90381eb8a8ae06855ea2b74f322bebbec/lottie/src/main/java/com/airbnb/lottie/LottieTask.java#L77-L113","documentation":"Thrown by LottieTask#setResult when result has already been assigned once. setResult is an internal single-assignment guard invoked from the task's runnable (inline on the main thread or via EXECUTOR); a second call indicates the task's result was set twice, which violates LottieTask's one-shot contract.","triggerScenarios":"Internal: the same LottieTask instance having its runnable complete twice (e.g. a reused task, a double notify, or a race where EXECUTOR and an inline path both call setResult). Not normally reachable through public API unless a task reference is reused or the listener pipeline re-enters setResult.","commonSituations":"Library version with a concurrency regression; manually poking a LottieTask; a wrapped/retry layer that re-runs a task that already produced a result.","solutions":["Do not reuse a LottieTask instance - create a new one per load via LottieCompositionFactory.","Upgrade lottie-android; this guard is internal and double-set indicates a bug or unsupported reuse.","If triggering from custom code, ensure you only consume the task's result via addListener/addFailureListener and never drive setResult yourself."],"exampleFix":"// before - reusing/retrying the same task\ntask.removeListener(...); runSameTaskAgain(task);\n\n// after - start a fresh task per attempt\nLottieTask<LottieComposition> task = LottieCompositionFactory.fromAsset(context, fileName);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Treat task as one-shot; never reuse. If you must retry, start a new task:\ntry {\n  task.addListener(c -> render(c)).addFailureListener(t -> handle(t));\n} catch (IllegalStateException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"set once\")) {\n    task = LottieCompositionFactory.fromAsset(ctx, fileName); // fresh task\n  } else throw e;\n}","preventionTips":["Never reuse a LottieTask; request a new one from LottieCompositionFactory for each load.","Keep a single ownership point for each load to avoid concurrent result setting.","Upgrade lottie-android if you see this spuriously - it is normally internal."],"tags":["task","internal","concurrency","state"],"backgroundTag":null,"analyzedSha":"05ea92e90381eb8a8ae06855ea2b74f322bebbec","analyzedAt":"2026-08-14T00:51:35.636Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}