A lateinit property is a non-null Kotlin property that is declared without an initial value and is assigned later. The compiler allows deferred initialisation, but any access before assignment throws a runtime exception, so it is mainly used where construction and initialisation happen separately.
Deferred initialisation in Kotlin
A lateinit property is a deliberate escape hatch for non-null state that cannot be assigned at construction time. It lets a class expose a non-null contract before the object is fully wired, but the trade-off is that any read before assignment fails at runtime rather than at compile time.
This pattern is most useful when an object’s lifecycle has a clear setup phase and a separate use phase, such as framework-managed injection, test setup, or UI binding. It reduces boilerplate around nullable placeholders, but it also shifts correctness from the type system to the programmer’s initialisation discipline.
Why lateinit exists and what it changes
Kotlin normally pushes developers toward fully initialised immutable state. lateinit changes that model by allowing a non-null property to be declared first and assigned later. That is why it is restricted to mutable properties of reference types, and why it is best understood as a lifecycle convenience rather than a general-purpose default.
The benefit is clarity at the point of use: downstream code can treat the property as non-null once initialisation has happened. The cost is temporal safety, because the property’s validity now depends on whether the object has crossed the right initialisation boundary.
Where it fits in object lifecycle
Late-initialised properties make the most sense when object construction and dependency wiring are separated. Common examples include dependency injection, Android component lifecycles, and tests that prepare state after instantiation. In each case, the codebase is signalling that the object exists before all of its usable state does.
That makes the lifecycle contract important. If the property is expected to be available only after a framework callback or setup method, the surrounding code must respect that boundary consistently. If the boundary is unclear, the property becomes a source of fragile assumptions rather than a convenience.
Failure modes and safe usage boundaries
The main failure mode is premature access. Because the compiler trusts the declared non-null type, the mistake is not caught where the property is declared, only when it is read too early. That creates a runtime failure mode that is easy to miss in code review if the initialisation path is spread across multiple methods or framework callbacks.
NIST SP 800-53 Rev 5 Security and Privacy Controls is useful here as a broader control reference for disciplined configuration and integrity expectations, while OWASP API Security Top 10 is a reminder that runtime trust in state can become a security issue when absent checks let code proceed with invalid assumptions.
Lateinit should stay bounded to properties that truly cannot be initialised earlier. If a value can be passed through a constructor, factory, or parameter object, that is usually a safer and more explicit design.
Alternatives and design trade-offs
When the object can be created in one step, constructor injection, immutable properties, or nullable types are usually better choices. Those alternatives make the initialisation state visible in the type system, which is easier to reason about and harder to misuse.
Use lateinit when it removes accidental complexity, not when it hides it. The best designs make the initialisation sequence obvious, keep the number of late-assigned properties small, and avoid turning a temporary setup concern into a long-lived correctness dependency.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
NIST SP 800-53 Rev 5 and OWASP ASVS set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| NIST SP 800-53 Rev 5 | IA-5 — Authenticator Management | Lateinit shifts correctness to controlled late assignment, making disciplined state setup important. |
| Recommendation — Enforce strict lifecycle handling for properties that are assigned after construction. | ||
| OWASP ASVS | V15 — Secure Coding and Architecture | The term is a code design choice that affects how state and object lifecycle are modeled. |
| Recommendation — Prefer designs that make initialisation state explicit in code structure. | ||
Practitioner Guidance
Common misunderstanding: lateinit does not mean “non-null but always ready.” It means “non-null after a separate assignment step,” so the real question is whether that step is guaranteed before any read can occur.
Governance implication: Treat each late-initialised property as a lifecycle contract. If the code depends on framework callbacks or external setup, make that dependency obvious in naming, structure, and tests so the initialisation boundary is hard to violate.
Related resources from NHI Mgmt Group
- How do teams stop AI assistants from exposing intellectual property and credentials?
- Why do virtual assets require different recovery procedures than other seized property?
- How should organisations protect intellectual property when employees use AI tools?
- What breaks when legacy DLP is used to protect intellectual property?
Deepen Your Knowledge
Free weekly newsletter
Subscribe to the NHI & AI Identity Journal
The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.
Bonus 33% off our NHI Course when you subscribe.
Reviewed and updated by the NHIMG editorial team on November 3, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org