FyroxEngine/Fyrox · error
Ticket index was invalid
Error message
Ticket index was invalid
What it means
Pool::put_back returns a previously take_reserve'd record to the pool using the ticket taken from take_reserve. The ticket's index must point to a valid pool record; if the ticket is stale, corrupted, duplicated, or belongs to another pool, records_get_mut returns None and the code panics.
Solutions
- Only use tickets returned by take_reserve on the same pool, exactly once
- Ensure each take_reserve is matched by exactly one put_back (no duplicates)
- Verify the pool was not recreated/cleared while the ticket was held
Example fix
// before pool.put_back(old_ticket, value); // ticket already consumed // after let (ticket, _) = pool.take_reserve(handle); // ... exactly once ... let handle = pool.put_back(ticket, value);
Defensive patterns
Strategy: type-guard
Validate before calling
// ensure ticket was produced by take_reserve on this pool and not yet consumed assert!(tickets.contains_key(&ticket.index));
Try / catch
// pre-condition check instead of catch: track live tickets in a set; on drop/put_back remove them exactly once
Prevention
- Never copy or clone Tickets; consume each exactly once
- Keep take_reserve/put_back pairs in the same scope or RAII guard
- Never share tickets across pool instances
When it happens
Trigger: Calling put_back with a Ticket that was not obtained from take_reserve on this same pool, a ticket used twice (forgotten handles / double put_back), or a ticket from a different pool instance.
Common situations: Undo/redo or frame-delayed reinsertion logic that stores tickets across pool rebuilds; copying ticket values and putting back twice; mixing tickets between pools of the same type.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Animation pool must be empty on load!
- An object at index must be returned to a pool it was taken…
- Attempt to spawn an object at pool record with payload!…
- Attempt to replace object in pool using dangling handle!…
- The handle must be valid!
AI-assisted analysis of FyroxEngine/Fyrox@76c91aad8e (2026-09-10).
Data as JSON: /api/errors/3c7923aa6602c15a.
Report an issue: GitHub.
Appendix: source
Thrown at fyrox-core/src/pool/mod.rs:1084
};
Ok((ticket, payload))
} else {
Err(PoolError::Empty(handle.into()))
}
} else {
Err(PoolError::InvalidGeneration(handle.generation))
}
}
/// Returns the value back into the pool using the given ticket. See [`take_reserve`] for more
/// information.
///
/// [`take_reserve`]: Pool::take_reserve
#[inline]
pub fn put_back(&mut self, ticket: Ticket<T>, value: T) -> Handle<T> {
let record = self
.records_get_mut(ticket.index)
.expect("Ticket index was invalid");
let old = record.payload.replace(value);
assert!(old.is_none());
let handle = Handle::new(ticket.index, record.generation);
std::mem::forget(ticket);
handle
}
/// Forgets that value at ticket was reserved and makes it usable again.
/// Useful when you don't need to put value back by ticket, but just make
/// pool record usable again.
#[inline]
pub fn forget_ticket(&mut self, ticket: Ticket<T>) {
self.free_stack.push(ticket.index);
std::mem::forget(ticket);
}
/// Returns total capacity of pool. Capacity has nothing about real amount of objects in pool!
#[inline]View on GitHub (pinned to 76c91aad8e)