airbnb/epoxy · error · IllegalStateException
Timer was already started
Error message
Timer was already started
What it means
DebugTimer.start() throws IllegalStateException if the timer's startTime is already set (not -1), meaning the same section was started twice without a stop()/reset() in between. The timer tracks a single start timestamp and section name, so a double start would silently overwrite measurements. The library fails fast to surface mis-sequenced timing calls.
Solutions
- Call stop() (which auto-resets) after each start() before starting again
- Call reset() before start() when the previous measurement is no longer needed
- Create a new DebugTimer instance for each independent section
- Guard the start call: only invoke start() if the section hasn't already been started
Example fix
// before
timer.start("bind");
timer.start("bind"); // throws
// after
timer.reset();
timer.start("bind"); Defensive patterns
Strategy: validation
Validate before calling
// ensure the timer is not already running before starting
if (timer.isStarted()) { timer.reset(); }
timer.start("bind"); Prevention
- Always pair start() with stop() in try/finally
- Use one timer instance per measured section
- Call reset() defensively before start() in re-bind paths
When it happens
Trigger: Calling start(sectionName) twice on the same DebugTimer instance without calling stop() or reset() between the calls.
Common situations: Debugging bind times in an Epoxy controller where the start call is inside a lifecycle method that runs more than once (e.g. onBindViewHolder re-binding the same holder, or a retry path), or accidentally creating two timing sections with the same shared timer instance.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Timer was not started
- Must have stable ids when saving view holder state
- State cannot be restored once views have been bound. It…
- Tried to restore instance state, but onSaveInstanceState…
- numItemsToPrefetch must be greater than 0
AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13).
Data as JSON: /api/errors/c75b8a686f5237fd.
Report an issue: GitHub.
Appendix: source
Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/DebugTimer.java:24
private final String tag;
private long startTime;
private String sectionName;
DebugTimer(String tag) {
this.tag = tag;
reset();
}
private void reset() {
startTime = -1;
sectionName = null;
}
@Override
public void start(String sectionName) {
if (startTime != -1) {
throw new IllegalStateException("Timer was already started");
}
startTime = System.nanoTime();
this.sectionName = sectionName;
}
@Override
public void stop() {
if (startTime == -1) {
throw new IllegalStateException("Timer was not started");
}
float durationMs = (System.nanoTime() - startTime) / 1000000f;
Log.d(tag, String.format(sectionName + ": %.3fms", durationMs));
reset();
}
}
View on GitHub (pinned to e45bd3a61f)