diff --git a/src/allocator.c b/src/allocator.c
index 4646dd81ea70111378fd2dce28d8a5a36fbc2275..cc259e605c56573b506f39194793e804ab4bf8b6 100644
--- a/src/allocator.c
+++ b/src/allocator.c
@@ -47,15 +47,20 @@ struct HArena_ {
   jmp_buf *except;
 };
 
+void* h_alloc(HAllocator* mm__, size_t size) {
+  void *p = mm__->alloc(mm__, size);
+  if(!p)
+    h_platform_errx(1, "memory allocation failed (%uB requested)\n", (unsigned int)size);
+  return p;
+}
+
 HArena *h_new_arena(HAllocator* mm__, size_t block_size) {
   if (block_size == 0)
     block_size = 4096;
   struct HArena_ *ret = h_new(struct HArena_, 1);
-  struct arena_link *link = (struct arena_link*)mm__->alloc(mm__, sizeof(struct arena_link) + block_size);
-  if (!link) {
-    // TODO: error-reporting -- let user know that arena link couldn't be allocated
-    return NULL;
-  }
+  struct arena_link *link = (struct arena_link*)h_alloc(mm__, sizeof(struct arena_link) + block_size);
+  assert(ret != NULL);
+  assert(link != NULL);
   memset(link, 0, sizeof(struct arena_link) + block_size);
   link->free = block_size;
   link->used = 0;
diff --git a/src/allocator.h b/src/allocator.h
index d80209db04dd748839e8287900a4f1602362879a..dc88af68f22895f584065a491463b3f8576c09e9 100644
--- a/src/allocator.h
+++ b/src/allocator.h
@@ -24,17 +24,6 @@
 extern "C" {
 #endif
 
-// TODO(thequux): Turn this into an "HAllocatorVtable", and add a wrapper that also takes an environment pointer.
-typedef struct HAllocator_ {
-  void* (*alloc)(struct HAllocator_* allocator, size_t size);
-  void* (*realloc)(struct HAllocator_* allocator, void* ptr, size_t size);
-  void (*free)(struct HAllocator_* allocator, void* ptr);
-} HAllocator;
-
-typedef struct HArena_ HArena ; // hidden implementation
-
-HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for default...
-
 #if defined __llvm__
 # if __has_attribute(malloc)
 #   define ATTR_MALLOC(n) __attribute__((malloc))
@@ -49,6 +38,19 @@ HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for def
 # define ATTR_MALLOC(n)
 #endif
 
+// TODO(thequux): Turn this into an "HAllocatorVtable", and add a wrapper that also takes an environment pointer.
+typedef struct HAllocator_ {
+  void* (*alloc)(struct HAllocator_* allocator, size_t size);
+  void* (*realloc)(struct HAllocator_* allocator, void* ptr, size_t size);
+  void (*free)(struct HAllocator_* allocator, void* ptr);
+} HAllocator;
+
+void* h_alloc(HAllocator* allocator, size_t size) ATTR_MALLOC(2);
+
+typedef struct HArena_ HArena ; // hidden implementation
+
+HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for default...
+
 void* h_arena_malloc(HArena *arena, size_t count) ATTR_MALLOC(2);
 void h_arena_free(HArena *arena, void* ptr); // For future expansion, with alternate memory managers.
 void h_delete_arena(HArena *arena);
diff --git a/src/bitwriter.c b/src/bitwriter.c
index 74e273448aded2ae40ec99666f230447054c0dd0..bcc21dd308a743a7dd98a6bc52364f75f2d75328 100644
--- a/src/bitwriter.c
+++ b/src/bitwriter.c
@@ -12,10 +12,8 @@
 HBitWriter *h_bit_writer_new(HAllocator* mm__) {
   HBitWriter *writer = h_new(HBitWriter, 1);
   memset(writer, 0, sizeof(*writer));
-  writer->buf = mm__->alloc(mm__, writer->capacity = 8);
-  if (!writer) {
-    return NULL;
-  }
+  writer->buf = h_alloc(mm__, writer->capacity = 8);
+  assert(writer != NULL);
   memset(writer->buf, 0, writer->capacity);
   writer->mm__ = mm__;
   writer->flags = BYTE_BIG_ENDIAN | BIT_BIG_ENDIAN;
diff --git a/src/internal.h b/src/internal.h
index 776f636811183a4b3e19de9de8c8ce5b2b66f27d..10db4b20f429283bbf0aa99928487b2754379d91 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -49,7 +49,7 @@
   rtype_t name##__m(HAllocator* mm__)
 // Functions with arguments are difficult to forward cleanly. Alas, we will need to forward them manually.
 
-#define h_new(type, count) ((type*)(mm__->alloc(mm__, sizeof(type)*(count))))
+#define h_new(type, count) ((type*)(h_alloc(mm__, sizeof(type)*(count))))
 #define h_free(addr) (mm__->free(mm__, (addr)))
 
 #ifndef __cplusplus
diff --git a/src/pprint.c b/src/pprint.c
index 11ec3d67411df66043ddd7880edeb22cb5d7db51..9c7c6522c0a201cf544ffaea3227510fec4bf827 100644
--- a/src/pprint.c
+++ b/src/pprint.c
@@ -186,13 +186,11 @@ static void unamb_sub(const HParsedToken* tok, struct result_buf *buf) {
 
 char* h_write_result_unamb(const HParsedToken* tok) {
   struct result_buf buf = {
-    .output = (&system_allocator)->alloc(&system_allocator, 16),
+    .output = h_alloc(&system_allocator, 16),
     .len = 0,
     .capacity = 16
   };
-  if (!buf.output) {
-    return NULL;
-  }
+  assert(buf.output != NULL);
   unamb_sub(tok, &buf);
   append_buf_c(&buf, 0);
   return buf.output;
diff --git a/src/registry.c b/src/registry.c
index 2ebac1a94ad37a501c7c10a50c3eb6a45fc74dd0..d905320bbdf6131e5ab449c525086e4b1205a28b 100644
--- a/src/registry.c
+++ b/src/registry.c
@@ -46,10 +46,8 @@ static int compare_entries(const void* v1, const void* v2) {
 }
 
 HTokenType h_allocate_token_type(const char* name) {
-  Entry* new_entry = (&system_allocator)->alloc(&system_allocator, sizeof(*new_entry));
-  if (!new_entry) {
-    return TT_INVALID;
-  }
+  Entry* new_entry = h_alloc(&system_allocator, sizeof(*new_entry));
+  assert(new_entry != NULL);
   new_entry->name = name;
   new_entry->value = 0;
   Entry* probe = *(Entry**)tsearch(new_entry, &tt_registry, compare_entries);