Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/fix-opennextconfig-null-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@opennextjs/aws": patch
---

fix: add null check for globalThis.openNextConfig in cache handler

Adds optional chaining when accessing globalThis.openNextConfig to prevent
TypeError during Next.js 16 build phase when using the Adapters API. The cache
handler can be instantiated during SSG/prerendering before openNextConfig is
initialized by the runtime handlers.
8 changes: 4 additions & 4 deletions packages/open-next/src/adapters/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default class Cache {
kind?: "FETCH";
},
) {
if (globalThis.openNextConfig.dangerous?.disableIncrementalCache) {
if (globalThis.openNextConfig?.dangerous?.disableIncrementalCache) {
return null;
}

Expand Down Expand Up @@ -204,7 +204,7 @@ export default class Cache {
data?: IncrementalCacheValue,
ctx?: IncrementalCacheContext,
): Promise<void> {
if (globalThis.openNextConfig.dangerous?.disableIncrementalCache) {
if (globalThis.openNextConfig?.dangerous?.disableIncrementalCache) {
return;
}
// This one might not even be necessary anymore
Expand Down Expand Up @@ -322,7 +322,7 @@ export default class Cache {
}

public async revalidateTag(tags: string | string[]) {
const config = globalThis.openNextConfig.dangerous;
const config = globalThis.openNextConfig?.dangerous;
if (config?.disableTagCache || config?.disableIncrementalCache) {
return;
}
Expand Down Expand Up @@ -430,7 +430,7 @@ export default class Cache {
ctx?: IncrementalCacheContext,
) {
if (
globalThis.openNextConfig.dangerous?.disableTagCache ||
globalThis.openNextConfig?.dangerous?.disableTagCache ||
globalThis.tagCache.mode === "nextMode" ||
// Here it means it's a delete
!data
Expand Down
28 changes: 28 additions & 0 deletions packages/tests-unit/tests/adapters/cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,34 @@ describe("CacheHandler", () => {
expect(result).toBeNull();
});

describe("undefined openNextConfig", () => {
it("Should not throw when globalThis.openNextConfig is undefined", async () => {
// @ts-expect-error - Testing undefined config scenario
globalThis.openNextConfig = undefined;

// Should not throw TypeError: Cannot read properties of undefined (reading 'dangerous')
const result = await cache.get("key");

expect(result).not.toBeUndefined();
});

it("Should not throw on set when globalThis.openNextConfig is undefined", async () => {
// @ts-expect-error - Testing undefined config scenario
globalThis.openNextConfig = undefined;

await expect(
cache.set("key", { kind: "REDIRECT", props: {} }),
).resolves.not.toThrow();
});

it("Should not throw on revalidateTag when globalThis.openNextConfig is undefined", async () => {
// @ts-expect-error - Testing undefined config scenario
globalThis.openNextConfig = undefined;

await expect(cache.revalidateTag("tag")).resolves.not.toThrow();
});
});

describe("disableIncrementalCache", () => {
beforeEach(() => {
globalThis.openNextConfig.dangerous.disableIncrementalCache = true;
Expand Down