From 9d86c5656e87351b1c710cb044a8e5c025a18760 Mon Sep 17 00:00:00 2001
From: Nic Barker <contact+github@nicbarker.com>
Date: Wed, 25 Dec 2024 20:52:22 +1300
Subject: [PATCH] Initial implementation of error callback

---
 clay.h                                        | 227 ++++++++++--------
 .../raylib-sidebar-scrolling-container/main.c |   2 +-
 generator/array_add.template.c                |   2 +-
 generator/array_add_value.template.c          |   2 +-
 generator/array_set.template.c                |   9 +-
 5 files changed, 130 insertions(+), 112 deletions(-)

diff --git a/clay.h b/clay.h
index 1ef0db9..28f13d7 100644
--- a/clay.h
+++ b/clay.h
@@ -435,17 +435,35 @@ typedef struct
     Clay_PointerDataInteractionState state;
 } Clay_PointerData;
 
+typedef enum {
+    CLAY_ERROR_TYPE_TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED,
+    CLAY_ERROR_TYPE_ARENA_CAPACITY_EXCEEDED,
+    CLAY_ERROR_TYPE_ELEMENTS_CAPACITY_EXCEEDED,
+    CLAY_ERROR_TYPE_TEXT_MEASUREMENT_CAPACITY_EXCEEDED,
+    CLAY_ERROR_TYPE_DUPLICATE_ID,
+    CLAY_ERROR_TYPE_FLOATING_CONTAINER_PARENT_NOT_FOUND,
+    CLAY_ERROR_TYPE_INTERNAL_ERROR,
+} Clay_ErrorType;
+
 typedef struct
 {
+    Clay_ErrorType errorType;
     Clay_String errorText;
+    uintptr_t userData;
 } Clay_ErrorData;
 
+typedef struct
+{
+    void (*errorHandlerFunction)(Clay_ErrorData errorText);
+    uintptr_t userData;
+} Clay_ErrorHandler;
+
 // Function Forward Declarations ---------------------------------
 // Public API functions ---
 uint32_t Clay_MinMemorySize();
 Clay_Arena Clay_CreateArenaWithCapacityAndMemory(uint32_t capacity, void *offset);
 void Clay_SetPointerState(Clay_Vector2 position, bool pointerDown);
-void Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, void (*errorHandlerFunction)(Clay_ErrorData errorText));
+void Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler);
 void Clay_UpdateScrollContainers(bool enableDragScrolling, Clay_Vector2 scrollDelta, float deltaTime);
 void Clay_SetLayoutDimensions(Clay_Dimensions dimensions);
 void Clay_BeginLayout();
@@ -482,7 +500,6 @@ void Clay__OpenTextElement(Clay_String text, Clay_TextElementConfig *textConfig)
 
 extern Clay_Color Clay__debugViewHighlightColor;
 extern uint32_t Clay__debugViewWidth;
-extern bool Clay__debugMaxElementsLatch;
 
 #ifdef __cplusplus
 }
@@ -497,11 +514,11 @@ extern bool Clay__debugMaxElementsLatch;
 #undef CLAY_IMPLEMENTATION
 
 #ifndef CLAY_MAX_ELEMENT_COUNT
-#define CLAY_MAX_ELEMENT_COUNT 8192
+#define CLAY_MAX_ELEMENT_COUNT 128
 #endif
 
 #ifndef CLAY__TEXT_MEASURE_HASH_BUCKET_COUNT
-#define CLAY__TEXT_MEASURE_HASH_BUCKET_COUNT 128
+#define CLAY__TEXT_MEASURE_HASH_BUCKET_COUNT 16
 #endif
 
 #ifndef CLAY_MEASURE_TEXT_CACHE_SIZE
@@ -517,7 +534,7 @@ extern bool Clay__debugMaxElementsLatch;
 #endif
 
 bool Clay__warningsEnabled = true;
-void (*Clay__errorHandler)(Clay_ErrorData errorText);
+Clay_ErrorHandler Clay__errorHandler = CLAY__INIT(Clay_ErrorHandler) { .errorHandlerFunction = Clay__Noop };
 
 void Clay__Noop() {};
 
@@ -528,7 +545,7 @@ typedef struct
 {
     bool maxElementsExceeded;
     bool maxRenderCommandsExceeded;
-    bool maxStringMeasureCacheExceeded;
+    bool maxTextMeasureCacheExceeded;
 } Clay_BooleanWarnings;
 
 Clay_BooleanWarnings Clay__booleanWarnings;
@@ -560,7 +577,10 @@ Clay__WarningArray Clay__WarningArray_Allocate_Arena(uint32_t capacity, Clay_Are
         arena->nextAllocation = arenaOffsetAligned + totalSizeBytes;
     }
     else {
-        Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("Clay encountered an internal memory capacity overflow. Try increasing CLAY_MAX_ELEMENT_COUNT") });
+        Clay__errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) {
+            .errorType = CLAY_ERROR_TYPE_ARENA_CAPACITY_EXCEEDED,
+            .errorText = CLAY_STRING("Clay attempted to allocate memory in its arena, but ran out of capacity. Try increasing the capacity of the arena passed to Clay_Initialize()"),
+            .userData = Clay__errorHandler.userData });
     }
     return array;
 }
@@ -573,9 +593,6 @@ Clay__Warning *Clay__WarningArray_Add(Clay__WarningArray *array, Clay__Warning i
         array->internalArray[array->length++] = item;
         return &array->internalArray[array->length - 1];
     }
-    else {
-        Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("Clay encountered an internal memory capacity overflow. Try increasing CLAY_MAX_ELEMENT_COUNT") });
-    }
     return &CLAY__WARNING_DEFAULT;
 }
 
@@ -590,10 +607,10 @@ void* Clay__Array_Allocate_Arena(uint32_t capacity, uint32_t itemSize, uint32_t
         return (void*)((uintptr_t)arena->memory + (uintptr_t)arenaOffsetAligned);
     }
     else {
-        if (Clay__warningsEnabled) {
-            Clay__WarningArray_Add(&Clay_warnings, CLAY__INIT(Clay__Warning) { CLAY_STRING("Attempting to allocate array in arena, but arena is already at capacity and would overflow.") });
-        }
-        Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("Clay encountered an internal memory capacity overflow. Try increasing CLAY_MAX_ELEMENT_COUNT") });
+        Clay__errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) {
+                .errorType = CLAY_ERROR_TYPE_ARENA_CAPACITY_EXCEEDED,
+                .errorText = CLAY_STRING("Clay attempted to allocate memory in its arena, but ran out of capacity. Try increasing the capacity of the arena passed to Clay_Initialize()"),
+                .userData = Clay__errorHandler.userData });
     }
     return CLAY__NULL;
 }
@@ -603,22 +620,22 @@ bool Clay__Array_RangeCheck(int index, uint32_t length)
     if (index < length && index >= 0) {
         return true;
     }
-    if (Clay__warningsEnabled) {
-        Clay__WarningArray_Add(&Clay_warnings, CLAY__INIT(Clay__Warning) { CLAY_STRING("Array access out of bounds.") });
-    }
-    Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("Clay encountered an internal memory capacity overflow. Try increasing CLAY_MAX_ELEMENT_COUNT") });
+    Clay__errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) {
+            .errorType = CLAY_ERROR_TYPE_INTERNAL_ERROR,
+            .errorText = CLAY_STRING("Clay attempted to make an out of bounds array access. This is an internal error and is likely a bug."),
+            .userData = Clay__errorHandler.userData });
     return false;
 }
 
-bool Clay__Array_IncrementCapacityCheck(uint32_t length, uint32_t capacity)
+bool Clay__Array_AddCapacityCheck(uint32_t length, uint32_t capacity)
 {
     if (length < capacity) {
         return true;
     }
-    if (Clay__warningsEnabled && !Clay__debugMaxElementsLatch) {
-        Clay__WarningArray_Add(&Clay_warnings, CLAY__INIT(Clay__Warning) { CLAY_STRING("Attempting to add to array that is already at capacity.") });
-    }
-    Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("Clay encountered an internal memory capacity overflow. Try increasing CLAY_MAX_ELEMENT_COUNT") });
+    Clay__errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) {
+        .errorType = CLAY_ERROR_TYPE_INTERNAL_ERROR,
+        .errorText = CLAY_STRING("Clay attempted to make an out of bounds array access. This is an internal error and is likely a bug."),
+        .userData = Clay__errorHandler.userData });
     return false;
 }
 
@@ -655,7 +672,7 @@ Clay_ElementId *Clay__ElementIdArray_Get(Clay__ElementIdArray *array, int index)
     return Clay__Array_RangeCheck(index, array->length) ? &array->internalArray[index] : &CLAY__ELEMENT_ID_DEFAULT;
 }
 Clay_ElementId *Clay__ElementIdArray_Add(Clay__ElementIdArray *array, Clay_ElementId item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -686,7 +703,7 @@ Clay_ElementConfig *Clay__ElementConfigArray_Get(Clay__ElementConfigArray *array
     return Clay__Array_RangeCheck(index, array->length) ? &array->internalArray[index] : &CLAY__ELEMENT_CONFIG_DEFAULT;
 }
 Clay_ElementConfig *Clay__ElementConfigArray_Add(Clay__ElementConfigArray *array, Clay_ElementConfig item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -712,7 +729,7 @@ Clay__LayoutConfigArray Clay__LayoutConfigArray_Allocate_Arena(uint32_t capacity
     return CLAY__INIT(Clay__LayoutConfigArray){.capacity = capacity, .length = 0, .internalArray = (Clay_LayoutConfig *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_LayoutConfig), CLAY__ALIGNMENT(Clay_LayoutConfig), arena)};
 }
 Clay_LayoutConfig *Clay__LayoutConfigArray_Add(Clay__LayoutConfigArray *array, Clay_LayoutConfig item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -735,7 +752,7 @@ Clay__RectangleElementConfigArray Clay__RectangleElementConfigArray_Allocate_Are
     return CLAY__INIT(Clay__RectangleElementConfigArray){.capacity = capacity, .length = 0, .internalArray = (Clay_RectangleElementConfig *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_RectangleElementConfig), CLAY__ALIGNMENT(Clay_RectangleElementConfig), arena)};
 }
 Clay_RectangleElementConfig *Clay__RectangleElementConfigArray_Add(Clay__RectangleElementConfigArray *array, Clay_RectangleElementConfig item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -758,7 +775,7 @@ Clay__TextElementConfigArray Clay__TextElementConfigArray_Allocate_Arena(uint32_
     return CLAY__INIT(Clay__TextElementConfigArray){.capacity = capacity, .length = 0, .internalArray = (Clay_TextElementConfig *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_TextElementConfig), CLAY__ALIGNMENT(Clay_TextElementConfig), arena)};
 }
 Clay_TextElementConfig *Clay__TextElementConfigArray_Add(Clay__TextElementConfigArray *array, Clay_TextElementConfig item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -781,7 +798,7 @@ Clay__ImageElementConfigArray Clay__ImageElementConfigArray_Allocate_Arena(uint3
     return CLAY__INIT(Clay__ImageElementConfigArray){.capacity = capacity, .length = 0, .internalArray = (Clay_ImageElementConfig *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_ImageElementConfig), CLAY__ALIGNMENT(Clay_ImageElementConfig), arena)};
 }
 Clay_ImageElementConfig *Clay__ImageElementConfigArray_Add(Clay__ImageElementConfigArray *array, Clay_ImageElementConfig item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -804,7 +821,7 @@ Clay__FloatingElementConfigArray Clay__FloatingElementConfigArray_Allocate_Arena
     return CLAY__INIT(Clay__FloatingElementConfigArray){.capacity = capacity, .length = 0, .internalArray = (Clay_FloatingElementConfig *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_FloatingElementConfig), CLAY__ALIGNMENT(Clay_FloatingElementConfig), arena)};
 }
 Clay_FloatingElementConfig *Clay__FloatingElementConfigArray_Add(Clay__FloatingElementConfigArray *array, Clay_FloatingElementConfig item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -827,7 +844,7 @@ Clay__CustomElementConfigArray Clay__CustomElementConfigArray_Allocate_Arena(uin
     return CLAY__INIT(Clay__CustomElementConfigArray){.capacity = capacity, .length = 0, .internalArray = (Clay_CustomElementConfig *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_CustomElementConfig), CLAY__ALIGNMENT(Clay_CustomElementConfig), arena)};
 }
 Clay_CustomElementConfig *Clay__CustomElementConfigArray_Add(Clay__CustomElementConfigArray *array, Clay_CustomElementConfig item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -850,7 +867,7 @@ Clay__ScrollElementConfigArray Clay__ScrollElementConfigArray_Allocate_Arena(uin
     return CLAY__INIT(Clay__ScrollElementConfigArray){.capacity = capacity, .length = 0, .internalArray = (Clay_ScrollElementConfig *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_ScrollElementConfig), CLAY__ALIGNMENT(Clay_ScrollElementConfig), arena)};
 }
 Clay_ScrollElementConfig *Clay__ScrollElementConfigArray_Add(Clay__ScrollElementConfigArray *array, Clay_ScrollElementConfig item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -870,7 +887,7 @@ Clay__StringArray Clay__StringArray_Allocate_Arena(uint32_t capacity, Clay_Arena
     return CLAY__INIT(Clay__StringArray){.capacity = capacity, .length = 0, .internalArray = (Clay_String *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_String), CLAY__ALIGNMENT(Clay_String), arena)};
 }
 Clay_String *Clay__StringArray_Add(Clay__StringArray *array, Clay_String item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -904,7 +921,7 @@ Clay__TextElementData *Clay__TextElementDataArray_Get(Clay__TextElementDataArray
     return Clay__Array_RangeCheck(index, array->length) ? &array->internalArray[index] : &CLAY__TEXT_ELEMENT_DATA_DEFAULT;
 }
 Clay__TextElementData *Clay__TextElementDataArray_Add(Clay__TextElementDataArray *array, Clay__TextElementData item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -927,7 +944,7 @@ Clay__BorderElementConfigArray Clay__BorderElementConfigArray_Allocate_Arena(uin
     return CLAY__INIT(Clay__BorderElementConfigArray){.capacity = capacity, .length = 0, .internalArray = (Clay_BorderElementConfig *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_BorderElementConfig), CLAY__ALIGNMENT(Clay_BorderElementConfig), arena)};
 }
 Clay_BorderElementConfig *Clay__BorderElementConfigArray_Add(Clay__BorderElementConfigArray *array, Clay_BorderElementConfig item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -970,7 +987,7 @@ Clay_LayoutElementArray Clay_LayoutElementArray_Allocate_Arena(uint32_t capacity
     return CLAY__INIT(Clay_LayoutElementArray){.capacity = capacity, .length = 0, .internalArray = (Clay_LayoutElement *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_LayoutElement), CLAY__ALIGNMENT(Clay_LayoutElement), arena)};
 }
 Clay_LayoutElement *Clay_LayoutElementArray_Add(Clay_LayoutElementArray *array, Clay_LayoutElement item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -994,7 +1011,7 @@ Clay__LayoutElementPointerArray Clay__LayoutElementPointerArray_Allocate_Arena(u
     return CLAY__INIT(Clay__LayoutElementPointerArray){.capacity = capacity, .length = 0, .internalArray = (Clay_LayoutElement* *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_LayoutElement*), CLAY__ALIGNMENT(Clay_LayoutElement*), arena)};
 }
 Clay_LayoutElement* *Clay__LayoutElementPointerArray_Add(Clay__LayoutElementPointerArray *array, Clay_LayoutElement* item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -1023,13 +1040,13 @@ Clay_RenderCommandArray Clay_RenderCommandArray_Allocate_Arena(uint32_t capacity
     return CLAY__INIT(Clay_RenderCommandArray){.capacity = capacity, .length = 0, .internalArray = (Clay_RenderCommand *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay_RenderCommand), CLAY__ALIGNMENT(Clay_RenderCommand), arena)};
 }
 Clay_RenderCommand *Clay_RenderCommandArray_Add(Clay_RenderCommandArray *array, Clay_RenderCommand item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
 	return &CLAY__RENDER_COMMAND_DEFAULT;
 }
-Clay_RenderCommand *Clay_RenderCommandArray_Get(Clay_RenderCommandArray *array, int32_t index) {
+Clay_RenderCommand *Clay_RenderCommandArray_Get(Clay_RenderCommandArray *array, int index) {
     return Clay__Array_RangeCheck(index, array->length) ? &array->internalArray[index] : &CLAY__RENDER_COMMAND_DEFAULT;
 }
 #pragma endregion
@@ -1065,7 +1082,7 @@ Clay__ScrollContainerDataInternalArray Clay__ScrollContainerDataInternalArray_Al
     return CLAY__INIT(Clay__ScrollContainerDataInternalArray){.capacity = capacity, .length = 0, .internalArray = (Clay__ScrollContainerDataInternal *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay__ScrollContainerDataInternal), CLAY__ALIGNMENT(Clay__ScrollContainerDataInternal), arena)};
 }
 Clay__ScrollContainerDataInternal *Clay__ScrollContainerDataInternalArray_Add(Clay__ScrollContainerDataInternalArray *array, Clay__ScrollContainerDataInternal item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -1111,7 +1128,7 @@ Clay__DebugElementDataArray Clay__DebugElementDataArray_Allocate_Arena(uint32_t
     return CLAY__INIT(Clay__DebugElementDataArray){.capacity = capacity, .length = 0, .internalArray = (Clay__DebugElementData *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay__DebugElementData), CLAY__ALIGNMENT(Clay__DebugElementData), arena)};
 }
 Clay__DebugElementData *Clay__DebugElementDataArray_Add(Clay__DebugElementDataArray *array, Clay__DebugElementData item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -1152,7 +1169,7 @@ Clay_LayoutElementHashMapItem *Clay__LayoutElementHashMapItemArray_Get(Clay__Lay
     return Clay__Array_RangeCheck(index, array->length) ? &array->internalArray[index] : &CLAY__LAYOUT_ELEMENT_HASH_MAP_ITEM_DEFAULT;
 }
 Clay_LayoutElementHashMapItem *Clay__LayoutElementHashMapItemArray_Add(Clay__LayoutElementHashMapItemArray *array, Clay_LayoutElementHashMapItem item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -1186,18 +1203,13 @@ Clay__MeasuredWord *Clay__MeasuredWordArray_Get(Clay__MeasuredWordArray *array,
     return Clay__Array_RangeCheck(index, array->length) ? &array->internalArray[index] : &CLAY__MEASURED_WORD_DEFAULT;
 }
 void Clay__MeasuredWordArray_Set(Clay__MeasuredWordArray *array, int index, Clay__MeasuredWord value) {
-	if (index < array->capacity && index >= 0) {
+	if (Clay__Array_RangeCheck(index, array->capacity)) {
 		array->internalArray[index] = value;
 		array->length = index < array->length ? array->length : index + 1;
-	} else {
-	    if (Clay__warningsEnabled) {
-            Clay__WarningArray_Add(&Clay_warnings, CLAY__INIT(Clay__Warning) { CLAY_STRING("Attempting to allocate array in arena, but arena is already at capacity and would overflow.") });
-	    }
-        Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("TODO") });
 	}
 }
 Clay__MeasuredWord *Clay__MeasuredWordArray_Add(Clay__MeasuredWordArray *array, Clay__MeasuredWord item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -1233,21 +1245,16 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCacheItemArray_Get(Clay__MeasureTex
     return Clay__Array_RangeCheck(index, array->length) ? &array->internalArray[index] : &CLAY__MEASURE_TEXT_CACHE_ITEM_DEFAULT;
 }
 Clay__MeasureTextCacheItem *Clay__MeasureTextCacheItemArray_Add(Clay__MeasureTextCacheItemArray *array, Clay__MeasureTextCacheItem item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
 	return &CLAY__MEASURE_TEXT_CACHE_ITEM_DEFAULT;
 }
 void Clay__MeasureTextCacheItemArray_Set(Clay__MeasureTextCacheItemArray *array, int index, Clay__MeasureTextCacheItem value) {
-	if (index < array->capacity && index >= 0) {
+	if (Clay__Array_RangeCheck(index, array->capacity)) {
 		array->internalArray[index] = value;
 		array->length = index < array->length ? array->length : index + 1;
-	} else {
-	    if (Clay__warningsEnabled) {
-            Clay__WarningArray_Add(&Clay_warnings, CLAY__INIT(Clay__Warning) { CLAY_STRING("Attempting to allocate array in arena, but arena is already at capacity and would overflow.") });
-	    }
-        Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("TODO") });
 	}
 }
 #pragma endregion
@@ -1268,19 +1275,14 @@ int32_t Clay__int32_tArray_Get(Clay__int32_tArray *array, int index) {
     return Clay__Array_RangeCheck(index, array->length) ? array->internalArray[index] : -1;
 }
 void Clay__int32_tArray_Add(Clay__int32_tArray *array, int32_t item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 	}
 }
 void Clay__int32_tArray_Set(Clay__int32_tArray *array, int index, int32_t value) {
-	if (index < array->capacity && index >= 0) {
+	if (Clay__Array_RangeCheck(index, array->capacity)) {
 		array->internalArray[index] = value;
 		array->length = index < array->length ? array->length : index + 1;
-	} else {
-	    if (Clay__warningsEnabled) {
-            Clay__WarningArray_Add(&Clay_warnings, CLAY__INIT(Clay__Warning) { CLAY_STRING("Attempting to allocate array in arena, but arena is already at capacity and would overflow.") });
-	    }
-        Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("TODO") });
 	}
 }
 int32_t Clay__int32_tArray_RemoveSwapback(Clay__int32_tArray *array, int index) {
@@ -1316,7 +1318,7 @@ Clay__LayoutElementTreeNodeArray Clay__LayoutElementTreeNodeArray_Allocate_Arena
     return CLAY__INIT(Clay__LayoutElementTreeNodeArray){.capacity = capacity, .length = 0, .internalArray = (Clay__LayoutElementTreeNode *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay__LayoutElementTreeNode), CLAY__ALIGNMENT(Clay__LayoutElementTreeNode), arena)};
 }
 Clay__LayoutElementTreeNode *Clay__LayoutElementTreeNodeArray_Add(Clay__LayoutElementTreeNodeArray *array, Clay__LayoutElementTreeNode item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -1351,7 +1353,7 @@ Clay__LayoutElementTreeRootArray Clay__LayoutElementTreeRootArray_Allocate_Arena
     return CLAY__INIT(Clay__LayoutElementTreeRootArray){.capacity = capacity, .length = 0, .internalArray = (Clay__LayoutElementTreeRoot *)Clay__Array_Allocate_Arena(capacity, sizeof(Clay__LayoutElementTreeRoot), CLAY__ALIGNMENT(Clay__LayoutElementTreeRoot), arena)};
 }
 Clay__LayoutElementTreeRoot *Clay__LayoutElementTreeRootArray_Add(Clay__LayoutElementTreeRootArray *array, Clay__LayoutElementTreeRoot item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
@@ -1396,7 +1398,6 @@ bool Clay__externalScrollHandlingEnabled = false;
 uint32_t Clay__debugSelectedElementId = 0;
 uint32_t Clay__debugViewWidth = 400;
 Clay_Color Clay__debugViewHighlightColor = CLAY__INIT(Clay_Color) { 168, 66, 28, 100 };
-bool Clay__debugMaxElementsLatch = false;
 uint32_t Clay__generation = 0;
 uint64_t Clay__arenaResetOffset = 0;
 Clay_Arena Clay__internalArena;
@@ -1577,7 +1578,10 @@ Clay__MeasuredWord *Clay__AddMeasuredWord(Clay__MeasuredWord word, Clay__Measure
 
 Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_TextElementConfig *config) {
     if (!Clay__MeasureText) {
-        Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("Clay's internal MeasureText function is null. You may have forgotten to call Clay_SetMeasureTextFunction, or passed a NULL function pointer by mistake.") });
+        Clay__errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) {
+            .errorType = CLAY_ERROR_TYPE_TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED,
+            .errorText = CLAY_STRING("Clay's internal MeasureText function is null. You may have forgotten to call Clay_SetMeasureTextFunction(), or passed a NULL function pointer by mistake."),
+            .userData = Clay__errorHandler.userData });
         return NULL;
     }
     uint32_t id = Clay__HashTextWithConfig(text, config);
@@ -1626,7 +1630,13 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_Text
         measured = Clay__MeasureTextCacheItemArray_Get(&Clay__measureTextHashMapInternal, newItemIndex);
     } else {
         if (Clay__measureTextHashMapInternal.length == Clay__measureTextHashMapInternal.capacity - 1) {
-            Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("Clay has run out of space in it's internal text measurement cache. Try increasing CLAY_MEASURE_TEXT_CACHE_SIZE.") });
+            if (Clay__booleanWarnings.maxTextMeasureCacheExceeded) {
+                Clay__errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) {
+                        .errorType = CLAY_ERROR_TYPE_ELEMENTS_CAPACITY_EXCEEDED,
+                        .errorText = CLAY_STRING("Clay ran out of capacity while attempting to create render commands. This is usually caused by a large amount of wrapping text elements while close to the max element capacity. Try using Clay_SetMaxElementCount() with a higher value."),
+                        .userData = Clay__errorHandler.userData });
+                Clay__booleanWarnings.maxTextMeasureCacheExceeded = true;
+            }
             return &CLAY__MEASURE_TEXT_CACHE_ITEM_DEFAULT;
         }
         measured = Clay__MeasureTextCacheItemArray_Add(&Clay__measureTextHashMapInternal, newCacheItem);
@@ -1642,7 +1652,13 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_Text
     Clay__MeasuredWord *previousWord = &tempWord;
     while (end < text->length) {
         if (Clay__measuredWords.length == Clay__measuredWords.capacity - 1) {
-            Clay__errorHandler(CLAY__INIT(Clay_ErrorData) { .errorText = CLAY_STRING("Clay has run out of space in it's internal text measurement cache. Try increasing CLAY_MEASURE_TEXT_CACHE_SIZE.") });
+            if (!Clay__booleanWarnings.maxTextMeasureCacheExceeded) {
+                Clay__errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) {
+                    .errorType = CLAY_ERROR_TYPE_TEXT_MEASUREMENT_CAPACITY_EXCEEDED,
+                    .errorText = CLAY_STRING("Clay has run out of space in it's internal text measurement cache. Try increasing CLAY_MEASURE_TEXT_CACHE_SIZE."),
+                    .userData = Clay__errorHandler.userData });
+                Clay__booleanWarnings.maxTextMeasureCacheExceeded = true;
+            }
             return &CLAY__MEASURE_TEXT_CACHE_ITEM_DEFAULT;
         }
         char current = text->chars[end];
@@ -1706,9 +1722,10 @@ Clay_LayoutElementHashMapItem* Clay__AddHashMapItem(Clay_ElementId elementId, Cl
                 hashItem->layoutElement = layoutElement;
                 hashItem->debugData->collision = false;
             } else { // Multiple collisions this frame - two elements have the same ID
-                if (Clay__warningsEnabled) {
-                    Clay__WarningArray_Add(&Clay_warnings, CLAY__INIT(Clay__Warning) { CLAY_STRING("Duplicate ID detected for element: "), Clay__WriteStringToCharBuffer(&Clay__dynamicStringData, elementId.stringId) });
-                }
+                Clay__errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) {
+                    .errorType = CLAY_ERROR_TYPE_DUPLICATE_ID,
+                    .errorText = CLAY_STRING("An element with this ID was already previously declared during this layout."),
+                    .userData = Clay__errorHandler.userData });
                 if (Clay__debugModeEnabled) {
                     hashItem->debugData->collision = true;
                 }
@@ -1750,7 +1767,7 @@ void Clay__GenerateIdForAnonymousElement(Clay_LayoutElement *openLayoutElement)
 }
 
 void Clay__ElementPostConfiguration() {
-    if (Clay__debugMaxElementsLatch) {
+    if (Clay__booleanWarnings.maxElementsExceeded) {
         return;
     }
     Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement();
@@ -1792,7 +1809,10 @@ void Clay__ElementPostConfiguration() {
                     Clay_LayoutElementHashMapItem *parentItem = Clay__GetHashMapItem(floatingConfig->parentId);
                     clipElementId = Clay__int32_tArray_Get(&Clay__layoutElementClipElementIds, parentItem->layoutElement - Clay__layoutElements.internalArray);
                     if (!parentItem) {
-                        Clay__WarningArray_Add(&Clay_warnings, CLAY__INIT(Clay__Warning) { CLAY_STRING("Clay Warning: Couldn't find parent container to attach floating container to.") });
+                        Clay__errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) {
+                            .errorType = CLAY_ERROR_TYPE_FLOATING_CONTAINER_PARENT_NOT_FOUND,
+                            .errorText = CLAY_STRING("A floating element was declared with a parentId, but no element with that ID was found."),
+                            .userData = Clay__errorHandler.userData });
                     }
                 }
                 Clay__LayoutElementTreeRootArray_Add(&Clay__layoutElementTreeRoots, CLAY__INIT(Clay__LayoutElementTreeRoot) {
@@ -1835,7 +1855,7 @@ void Clay__ElementPostConfiguration() {
 }
 
 void Clay__CloseElement() {
-    if (Clay__debugMaxElementsLatch) {
+    if (Clay__booleanWarnings.maxElementsExceeded) {
         return;
     }
     Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement();
@@ -1929,8 +1949,8 @@ void Clay__CloseElement() {
 }
 
 void Clay__OpenElement() {
-    if (Clay__layoutElements.length == Clay__layoutElements.capacity - 1 || Clay__debugMaxElementsLatch) {
-        Clay__debugMaxElementsLatch = true;
+    if (Clay__layoutElements.length == Clay__layoutElements.capacity - 1 || Clay__booleanWarnings.maxElementsExceeded) {
+        Clay__booleanWarnings.maxElementsExceeded = true;
         return;
     }
     Clay_LayoutElement layoutElement = CLAY__INIT(Clay_LayoutElement) {};
@@ -1944,8 +1964,8 @@ void Clay__OpenElement() {
 }
 
 void Clay__OpenTextElement(Clay_String text, Clay_TextElementConfig *textConfig) {
-    if (Clay__layoutElements.length == Clay__layoutElements.capacity - 1 || Clay__debugMaxElementsLatch) {
-        Clay__debugMaxElementsLatch = true;
+    if (Clay__layoutElements.length == Clay__layoutElements.capacity - 1 || Clay__booleanWarnings.maxElementsExceeded) {
+        Clay__booleanWarnings.maxElementsExceeded = true;
         return;
     }
     Clay_LayoutElement *parentElement = Clay__GetOpenLayoutElement();
@@ -2284,7 +2304,13 @@ void Clay__AddRenderCommand(Clay_RenderCommand renderCommand) {
     if (Clay__renderCommands.length < Clay__renderCommands.capacity - 1) {
         Clay_RenderCommandArray_Add(&Clay__renderCommands, renderCommand);
     } else {
-        Clay__booleanWarnings.maxRenderCommandsExceeded = true;
+        if (!Clay__booleanWarnings.maxRenderCommandsExceeded) {
+            Clay__booleanWarnings.maxRenderCommandsExceeded = true;
+            Clay__errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) {
+                .errorType = CLAY_ERROR_TYPE_ELEMENTS_CAPACITY_EXCEEDED,
+                .errorText = CLAY_STRING("Clay ran out of capacity while attempting to create render commands. This is usually caused by a large amount of wrapping text elements while close to the max element capacity. Try using Clay_SetMaxElementCount() with a higher value."),
+                .userData = Clay__errorHandler.userData });
+        }
     }
 }
 
@@ -2322,7 +2348,6 @@ void Clay__CalculateFinalLayout() {
         int32_t wordIndex = measureTextCacheItem->measuredWordsStartIndex;
         while (wordIndex != -1) {
             if (Clay__wrappedTextLines.length > Clay__wrappedTextLines.capacity - 1) {
-                Clay__booleanWarnings.maxStringMeasureCacheExceeded = true;
                 break;
             }
             Clay__MeasuredWord *measuredWord = Clay__MeasuredWordArray_Get(&Clay__measuredWords, wordIndex);
@@ -2835,7 +2860,7 @@ void Clay__CalculateFinalLayout() {
 }
 
 void Clay__AttachId(Clay_ElementId elementId) {
-    if (Clay__debugMaxElementsLatch) {
+    if (Clay__booleanWarnings.maxElementsExceeded) {
         return;
     }
     Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement();
@@ -2845,27 +2870,27 @@ void Clay__AttachId(Clay_ElementId elementId) {
 }
 
 void Clay__AttachLayoutConfig(Clay_LayoutConfig *config) {
-    if (Clay__debugMaxElementsLatch) {
+    if (Clay__booleanWarnings.maxElementsExceeded) {
         return;
     }
     Clay__GetOpenLayoutElement()->layoutConfig = config;
 }
 void Clay__AttachElementConfig(Clay_ElementConfigUnion config, Clay__ElementConfigType type) {
-    if (Clay__debugMaxElementsLatch) {
+    if (Clay__booleanWarnings.maxElementsExceeded) {
         return;
     }
     Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement();
     openLayoutElement->elementConfigs.length++;
     Clay__ElementConfigArray_Add(&Clay__elementConfigBuffer, CLAY__INIT(Clay_ElementConfig) { .type = type, .config = config });
 }
-Clay_LayoutConfig * Clay__StoreLayoutConfig(Clay_LayoutConfig config) {  return Clay__debugMaxElementsLatch ? &CLAY_LAYOUT_DEFAULT : Clay__LayoutConfigArray_Add(&Clay__layoutConfigs, config); }
-Clay_RectangleElementConfig * Clay__StoreRectangleElementConfig(Clay_RectangleElementConfig config) {  return Clay__debugMaxElementsLatch ? &CLAY__RECTANGLE_ELEMENT_CONFIG_DEFAULT : Clay__RectangleElementConfigArray_Add(&Clay__rectangleElementConfigs, config); }
-Clay_TextElementConfig * Clay__StoreTextElementConfig(Clay_TextElementConfig config) {  return Clay__debugMaxElementsLatch ? &CLAY__TEXT_ELEMENT_CONFIG_DEFAULT : Clay__TextElementConfigArray_Add(&Clay__textElementConfigs, config); }
-Clay_ImageElementConfig * Clay__StoreImageElementConfig(Clay_ImageElementConfig config) {  return Clay__debugMaxElementsLatch ? &CLAY__IMAGE_ELEMENT_CONFIG_DEFAULT : Clay__ImageElementConfigArray_Add(&Clay__imageElementConfigs, config); }
-Clay_FloatingElementConfig * Clay__StoreFloatingElementConfig(Clay_FloatingElementConfig config) {  return Clay__debugMaxElementsLatch ? &CLAY__FLOATING_ELEMENT_CONFIG_DEFAULT : Clay__FloatingElementConfigArray_Add(&Clay__floatingElementConfigs, config); }
-Clay_CustomElementConfig * Clay__StoreCustomElementConfig(Clay_CustomElementConfig config) {  return Clay__debugMaxElementsLatch ? &CLAY__CUSTOM_ELEMENT_CONFIG_DEFAULT : Clay__CustomElementConfigArray_Add(&Clay__customElementConfigs, config); }
-Clay_ScrollElementConfig * Clay__StoreScrollElementConfig(Clay_ScrollElementConfig config) {  return Clay__debugMaxElementsLatch ? &CLAY__SCROLL_ELEMENT_CONFIG_DEFAULT : Clay__ScrollElementConfigArray_Add(&Clay__scrollElementConfigs, config); }
-Clay_BorderElementConfig * Clay__StoreBorderElementConfig(Clay_BorderElementConfig config) {  return Clay__debugMaxElementsLatch ? &CLAY__BORDER_ELEMENT_CONFIG_DEFAULT : Clay__BorderElementConfigArray_Add(&Clay__borderElementConfigs, config); }
+Clay_LayoutConfig * Clay__StoreLayoutConfig(Clay_LayoutConfig config) {  return Clay__booleanWarnings.maxElementsExceeded ? &CLAY_LAYOUT_DEFAULT : Clay__LayoutConfigArray_Add(&Clay__layoutConfigs, config); }
+Clay_RectangleElementConfig * Clay__StoreRectangleElementConfig(Clay_RectangleElementConfig config) {  return Clay__booleanWarnings.maxElementsExceeded ? &CLAY__RECTANGLE_ELEMENT_CONFIG_DEFAULT : Clay__RectangleElementConfigArray_Add(&Clay__rectangleElementConfigs, config); }
+Clay_TextElementConfig * Clay__StoreTextElementConfig(Clay_TextElementConfig config) {  return Clay__booleanWarnings.maxElementsExceeded ? &CLAY__TEXT_ELEMENT_CONFIG_DEFAULT : Clay__TextElementConfigArray_Add(&Clay__textElementConfigs, config); }
+Clay_ImageElementConfig * Clay__StoreImageElementConfig(Clay_ImageElementConfig config) {  return Clay__booleanWarnings.maxElementsExceeded ? &CLAY__IMAGE_ELEMENT_CONFIG_DEFAULT : Clay__ImageElementConfigArray_Add(&Clay__imageElementConfigs, config); }
+Clay_FloatingElementConfig * Clay__StoreFloatingElementConfig(Clay_FloatingElementConfig config) {  return Clay__booleanWarnings.maxElementsExceeded ? &CLAY__FLOATING_ELEMENT_CONFIG_DEFAULT : Clay__FloatingElementConfigArray_Add(&Clay__floatingElementConfigs, config); }
+Clay_CustomElementConfig * Clay__StoreCustomElementConfig(Clay_CustomElementConfig config) {  return Clay__booleanWarnings.maxElementsExceeded ? &CLAY__CUSTOM_ELEMENT_CONFIG_DEFAULT : Clay__CustomElementConfigArray_Add(&Clay__customElementConfigs, config); }
+Clay_ScrollElementConfig * Clay__StoreScrollElementConfig(Clay_ScrollElementConfig config) {  return Clay__booleanWarnings.maxElementsExceeded ? &CLAY__SCROLL_ELEMENT_CONFIG_DEFAULT : Clay__ScrollElementConfigArray_Add(&Clay__scrollElementConfigs, config); }
+Clay_BorderElementConfig * Clay__StoreBorderElementConfig(Clay_BorderElementConfig config) {  return Clay__booleanWarnings.maxElementsExceeded ? &CLAY__BORDER_ELEMENT_CONFIG_DEFAULT : Clay__BorderElementConfigArray_Add(&Clay__borderElementConfigs, config); }
 
 #pragma region DebugTools
 Clay_Color CLAY__DEBUGVIEW_COLOR_1 = CLAY__INIT(Clay_Color) {58, 56, 52, 255};
@@ -3491,7 +3516,7 @@ void Clay_SetLayoutDimensions(Clay_Dimensions dimensions) {
 
 CLAY_WASM_EXPORT("Clay_SetPointerState")
 void Clay_SetPointerState(Clay_Vector2 position, bool isPointerDown) {
-    if (Clay__debugMaxElementsLatch) {
+    if (Clay__booleanWarnings.maxElementsExceeded) {
         return;
     }
     Clay__pointerInfo.position = position;
@@ -3558,7 +3583,7 @@ void Clay_SetPointerState(Clay_Vector2 position, bool isPointerDown) {
 }
 
 CLAY_WASM_EXPORT("Clay_Initialize")
-void Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, void (*errorHandlerFunction)(Clay_ErrorData errorText)) {
+void Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler) {
     Clay__internalArena = arena;
     Clay__InitializePersistentMemory(&Clay__internalArena);
     Clay__InitializeEphemeralMemory(&Clay__internalArena);
@@ -3570,7 +3595,7 @@ void Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, void (*
     }
     Clay__measureTextHashMapInternal.length = 1; // Reserve the 0 value to mean "no next element"
     Clay__layoutDimensions = layoutDimensions;
-    Clay__errorHandler = errorHandlerFunction;
+    Clay__errorHandler = errorHandler;
 }
 
 CLAY_WASM_EXPORT("Clay_UpdateScrollContainers")
@@ -3696,9 +3721,9 @@ void Clay_BeginLayout() {
     if (Clay__debugModeEnabled) {
         rootDimensions.width -= (float)Clay__debugViewWidth;
     }
-    if (Clay__debugMaxElementsLatch) {
-        return;
-    }
+    Clay__booleanWarnings.maxElementsExceeded = false;
+    Clay__booleanWarnings.maxTextMeasureCacheExceeded = false;
+    Clay__booleanWarnings.maxRenderCommandsExceeded = false;
     Clay__OpenElement();
     CLAY_ID("Clay__RootContainer");
     CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED((rootDimensions.width)), CLAY_SIZING_FIXED(rootDimensions.height)} });
@@ -3718,7 +3743,7 @@ Clay_RenderCommandArray Clay_EndLayout()
         Clay__RenderDebugView();
         Clay__warningsEnabled = true;
     }
-    if (Clay__debugMaxElementsLatch) {
+    if (Clay__booleanWarnings.maxElementsExceeded) {
         Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand ) { .boundingBox = { Clay__layoutDimensions.width / 2 - 59 * 4, Clay__layoutDimensions.height / 2 },  .config = { .textElementConfig = &Clay__DebugView_ErrorTextConfig }, .text = CLAY_STRING("Clay Error: Layout elements exceeded CLAY_MAX_ELEMENT_COUNT"), .commandType = CLAY_RENDER_COMMAND_TYPE_TEXT });
     } else {
         Clay__CalculateFinalLayout();
@@ -3737,7 +3762,7 @@ Clay_ElementId Clay_GetElementIdWithIndex(Clay_String idString, uint32_t index)
 }
 
 bool Clay_Hovered() {
-    if (Clay__debugMaxElementsLatch) {
+    if (Clay__booleanWarnings.maxElementsExceeded) {
         return false;
     }
     Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement();
@@ -3754,7 +3779,7 @@ bool Clay_Hovered() {
 }
 
 void Clay_OnHover(void (*onHoverFunction)(Clay_ElementId elementId, Clay_PointerData pointerInfo, intptr_t userData), intptr_t userData) {
-    if (Clay__debugMaxElementsLatch) {
+    if (Clay__booleanWarnings.maxElementsExceeded) {
         return;
     }
     Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement();
diff --git a/examples/raylib-sidebar-scrolling-container/main.c b/examples/raylib-sidebar-scrolling-container/main.c
index 4f54d8e..61b9481 100644
--- a/examples/raylib-sidebar-scrolling-container/main.c
+++ b/examples/raylib-sidebar-scrolling-container/main.c
@@ -210,7 +210,7 @@ int main(void) {
     uint64_t totalMemorySize = Clay_MinMemorySize();
     Clay_Arena clayMemory = (Clay_Arena) { .label = CLAY_STRING("Clay Memory Arena"), .memory = malloc(totalMemorySize), .capacity = totalMemorySize };
     Clay_SetMeasureTextFunction(Raylib_MeasureText);
-    Clay_Initialize(clayMemory, (Clay_Dimensions) { (float)GetScreenWidth(), (float)GetScreenHeight() }, Clay__errorHandler);
+    Clay_Initialize(clayMemory, (Clay_Dimensions) { (float)GetScreenWidth(), (float)GetScreenHeight() }, (Clay_ErrorHandler) { HandleClayErrors });
     Clay_Raylib_Initialize(1024, 768, "Clay - Raylib Renderer Example", FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI | FLAG_MSAA_4X_HINT);
     profilePicture = LoadTextureFromImage(LoadImage("resources/profile-picture.png"));
     Raylib_fonts[FONT_ID_BODY_24] = (Raylib_Font) {
diff --git a/generator/array_add.template.c b/generator/array_add.template.c
index 847cbcc..a51f891 100644
--- a/generator/array_add.template.c
+++ b/generator/array_add.template.c
@@ -1,5 +1,5 @@
 $TYPE$ *$NAME$_Add($NAME$ *array, $TYPE$ item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 		return &array->internalArray[array->length - 1];
 	}
diff --git a/generator/array_add_value.template.c b/generator/array_add_value.template.c
index 53dde0d..a153146 100644
--- a/generator/array_add_value.template.c
+++ b/generator/array_add_value.template.c
@@ -1,5 +1,5 @@
 void $NAME$_Add($NAME$ *array, $TYPE$ item) {
-	if (Clay__Array_IncrementCapacityCheck(array->length, array->capacity)) {
+	if (Clay__Array_AddCapacityCheck(array->length, array->capacity)) {
 		array->internalArray[array->length++] = item;
 	}
 }
\ No newline at end of file
diff --git a/generator/array_set.template.c b/generator/array_set.template.c
index 31bbc6a..c83d335 100644
--- a/generator/array_set.template.c
+++ b/generator/array_set.template.c
@@ -1,13 +1,6 @@
 void $NAME$_Set($NAME$ *array, int index, $TYPE$ value) {
-	if (index < array->capacity && index >= 0) {
+	if (Clay__Array_RangeCheck(index, array->capacity)) {
 		array->internalArray[index] = value;
 		array->length = index < array->length ? array->length : index + 1;
-	} else {
-	    if (Clay__warningsEnabled) {
-            Clay__WarningArray_Add(&Clay_warnings, CLAY__INIT(Clay__Warning) { CLAY_STRING("Attempting to allocate array in arena, but arena is already at capacity and would overflow.") });
-	    }
-        #ifdef CLAY_OVERFLOW_TRAP
-        raise(SIGTRAP);
-        #endif
 	}
 }
\ No newline at end of file