Nitrogen crashes with self-referential struct types (Maximum call stack size exceeded)
What happened?
When defining a self-referential struct type, Nitrogen crashes with RangeError: Maximum call stack size exceeded.
See https://github.com/mrousavy/nitro/pull/1069
Nitrogen CLI logs (with --logLevel="debug")
$ npx nitrogen --logLevel="debug"
🔧 Loading nitro.json config...
🚀 Nitrogen 0.31.10 runs at ~/rg/_libraries/nitro/packages/react-native-nitro-test
🔍 Nitrogen found 1 spec in ./src/specs
⏳ Parsing Cyclic.nitro.ts...
⚙️ Generating specs for HybridObject "Cyclic"...
❌ Failed to generate spec for Cyclic! RangeError: Maximum call stack size exceeded
❌ No specs found in Cyclic.nitro.ts!
⛓️ Setting up build configs for autolinking...
Creating autolinking build setup for ios...
Ruby: Creating NitroTest+autolinking.rb...
C++: Creating NitroTest-Swift-Cxx-Bridge.hpp...
C++: Creating NitroTest-Swift-Cxx-Bridge.cpp...
C++: Creating NitroTest-Swift-Cxx-Umbrella.hpp...
Objective-c++: Creating NitroTestAutolinking.mm...
Swift: Creating NitroTestAutolinking.swift...
🎉 Generated 0/1 HybridObjects in 0.7s!
💡 Your code is in ./nitrogen/generated
Nitro Specs (.nitro.ts)
import type { HybridObject } from 'react-native-nitro-modules'
export interface Node {
node?: Node
}
export interface Cyclic
extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
node?: Node
}
Nitro Modules Version
0.31.10
Nitrogen Version
0.31.10
Operating system
MacOS
Additional information
- [x] I have read and followed the Troubleshooting Guide.
- [x] I created a reproduction PR to reproduce this issue here in the nitro repo. (See Contributing for more information)
- [x] I searched for similar issues in this repository and found none.
JFYI; this will not be supported. A struct cannot reference itself cyclically, not in C++, not in Swift. Unless you make it a pointer/heap-allocated, but I don't think we should do that.
I should throw a better error tho :)
Thanks for the explanation! Updated the PR with a more helpful error message that shows examples of both direct and indirect cyclic references, plus a link to some added docs to the struct section: https://github.com/mrousavy/nitro/pull/1071
Hmm actually there are still stack overflow issues happening with valid non-cyclic patterns like structs containing callbacks that reference the same struct type:
export interface RequestConfig {
transform?: (request: RequestConfig) => Promise<RequestConfig>
}
#1072 adds a failing test case for this
I've opened a (Claude Code assisted) PR to address this: #1074
The fix handles cyclic struct references by:
- Detecting direct/indirect recursive structs (A→A or A→B→A) and throwing a clear error
- Supporting structs with callbacks that reference the same struct type (like the
transform?: (config: MyStruct) => Promise<MyStruct>example) - Generating separate
.hpp/.cppfiles for types with cyclic dependencies to avoid circular includes in the JNI headers