Skip to content

Commit 97aac58

Browse files
committed
fix(integrations): resolve Server Components crash on the integration detail page
Root cause (confirmed via staging server logs, digest 783665031): the [block] page.tsx is a server component whose Suspense fallback rendered <ChipLink leftIcon={ArrowLeft}> — passing the lucide icon (a function) across the server->client boundary, which React rejects ("Functions cannot be passed directly to Client Components"). This surfaced as the integrations error boundary / "Failed to load integrations" on soft navigation to a detail page. Move the fallback into a client component so the icon never crosses the boundary.
1 parent bca7f2c commit 97aac58

2 files changed

Lines changed: 35 additions & 13 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use client'
2+
3+
import { ChipLink } from '@sim/emcn'
4+
import { ArrowLeft } from 'lucide-react'
5+
6+
interface IntegrationBlockDetailFallbackProps {
7+
workspaceId: string
8+
}
9+
10+
/**
11+
* Suspense fallback for the integration detail page — the back-link chrome
12+
* shown while {@link IntegrationBlockDetail} hydrates.
13+
*
14+
* This MUST be a client component. The lucide `ArrowLeft` passed as `ChipLink`'s
15+
* `leftIcon` is a function, and functions cannot cross the server→client
16+
* boundary as props. Rendering the fallback from the server `page.tsx` directly
17+
* threw a React Server Components error ("Functions cannot be passed directly to
18+
* Client Components") that surfaced as the integrations error boundary. Keeping
19+
* the icon inside a client component avoids the boundary crossing entirely.
20+
*/
21+
export function IntegrationBlockDetailFallback({
22+
workspaceId,
23+
}: IntegrationBlockDetailFallbackProps) {
24+
return (
25+
<div className='flex h-full flex-col bg-[var(--bg)]'>
26+
<div className='flex flex-shrink-0 items-center bg-[var(--bg)] px-[16px] pt-[8.5px] pb-[8.5px]'>
27+
<ChipLink href={`/workspace/${workspaceId}/integrations`} leftIcon={ArrowLeft}>
28+
Integrations
29+
</ChipLink>
30+
</div>
31+
</div>
32+
)
33+
}

apps/sim/app/workspace/[workspaceId]/integrations/[block]/page.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import { Suspense } from 'react'
2-
import { ChipLink } from '@sim/emcn'
3-
import { ArrowLeft } from 'lucide-react'
42
import type { Metadata } from 'next'
53
import { notFound } from 'next/navigation'
64
import { INTEGRATIONS } from '@/lib/integrations'
75
import { IntegrationBlockDetail } from '@/app/workspace/[workspaceId]/integrations/[block]/integration-block-detail'
6+
import { IntegrationBlockDetailFallback } from '@/app/workspace/[workspaceId]/integrations/[block]/integration-block-detail-fallback'
87

98
export async function generateMetadata({
109
params,
@@ -28,17 +27,7 @@ export default async function IntegrationBlockPage({
2827
if (!integration) notFound()
2928

3029
return (
31-
<Suspense
32-
fallback={
33-
<div className='flex h-full flex-col bg-[var(--bg)]'>
34-
<div className='flex flex-shrink-0 items-center bg-[var(--bg)] px-[16px] pt-[8.5px] pb-[8.5px]'>
35-
<ChipLink href={`/workspace/${workspaceId}/integrations`} leftIcon={ArrowLeft}>
36-
Integrations
37-
</ChipLink>
38-
</div>
39-
</div>
40-
}
41-
>
30+
<Suspense fallback={<IntegrationBlockDetailFallback workspaceId={workspaceId} />}>
4231
<IntegrationBlockDetail integration={integration} workspaceId={workspaceId} />
4332
</Suspense>
4433
)

0 commit comments

Comments
 (0)