Skip to content

Commit da84397

Browse files
fix(build): stop uploads setup from sweeping the project into route graphs
next build (Turbopack) failed with "Two or more assets with different content were emitted to the same output path" on the server-root chunk. Root cause: setup.server.ts's unscoped path.resolve(process.cwd()) made node-file-tracing sweep the entire project — next.config.ts included — into every route graph reaching lib/uploads (the files/upload route and, since the export job, the export-async path). Two producers emitted the swept config into same-named chunks; staging's latest commits made their contents diverge and the names collided. Annotate the path derivation with turbopackIgnore per the NFT warning's own remediation — the build passes and all ~390 "unexpected file in NFT list" warnings disappear. Also inline the releaseJobClaim dynamic imports in the kickoff routes to plain static imports — service is already statically imported there. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent a8daebc commit da84397

7 files changed

Lines changed: 63 additions & 46 deletions

File tree

apps/sim/app/api/table/[tableId]/delete-async/route.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { runDetached } from '@/lib/core/utils/background'
99
import { generateRequestId } from '@/lib/core/utils/request'
1010
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1111
import { runTableDelete } from '@/lib/table/delete-runner'
12-
import { markTableJobRunning } from '@/lib/table/service'
12+
import { markTableJobRunning, releaseJobClaim } from '@/lib/table/service'
1313
import type { TableDeleteJobPayload } from '@/lib/table/types'
1414
import { accessError, checkAccess, tableFilterError } from '@/app/api/table/utils'
1515

@@ -98,7 +98,6 @@ export const POST = withRouteHandler(async (request: NextRequest, { params }: Ro
9898
} catch (error) {
9999
// A failed dispatch must not leave a ghost `running` job holding the
100100
// table's one-write-job slot until the stale-job janitor fires.
101-
const { releaseJobClaim } = await import('@/lib/table/service')
102101
await releaseJobClaim(tableId, jobId).catch(() => {})
103102
throw error
104103
}

apps/sim/app/api/table/[tableId]/export-async/route.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { runDetached } from '@/lib/core/utils/background'
99
import { generateRequestId } from '@/lib/core/utils/request'
1010
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1111
import { runTableExport, type TableExportPayload } from '@/lib/table/export-runner'
12-
import { markTableJobRunning } from '@/lib/table/service'
12+
import { markTableJobRunning, releaseJobClaim } from '@/lib/table/service'
1313
import type { TableExportJobPayload } from '@/lib/table/types'
1414
import { accessError, checkAccess } from '@/app/api/table/utils'
1515

@@ -71,7 +71,6 @@ export const POST = withRouteHandler(async (request: NextRequest, { params }: Ro
7171
} catch (error) {
7272
// A failed dispatch must not leave a ghost `running` job holding the
7373
// table's one-write-job slot until the stale-job janitor fires.
74-
const { releaseJobClaim } = await import('@/lib/table/service')
7574
await releaseJobClaim(tableId, jobId).catch(() => {})
7675
throw error
7776
}

apps/sim/app/api/table/[tableId]/import-async/route.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { runDetached } from '@/lib/core/utils/background'
99
import { generateRequestId } from '@/lib/core/utils/request'
1010
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1111
import { runTableImport, type TableImportPayload } from '@/lib/table/import-runner'
12-
import { markTableJobRunning } from '@/lib/table/service'
12+
import { markTableJobRunning, releaseJobClaim } from '@/lib/table/service'
1313
import { accessError, checkAccess } from '@/app/api/table/utils'
1414

1515
const logger = createLogger('TableImportIntoAsync')
@@ -93,7 +93,6 @@ export const POST = withRouteHandler(async (request: NextRequest, { params }: Ro
9393
} catch (error) {
9494
// A failed dispatch must not leave a ghost `running` job holding the
9595
// table's one-write-job slot until the stale-job janitor fires.
96-
const { releaseJobClaim } = await import('@/lib/table/service')
9796
await releaseJobClaim(tableId, importId).catch(() => {})
9897
throw error
9998
}

apps/sim/app/api/table/import-async/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1111
import { captureServerEvent } from '@/lib/posthog/server'
1212
import {
1313
createTable,
14+
deleteTable,
1415
getWorkspaceTableLimits,
1516
listTables,
17+
releaseJobClaim,
1618
sanitizeName,
1719
TABLE_LIMITS,
1820
TableConflictError,
@@ -125,7 +127,6 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
125127
// table's one-write-job slot — nor, in create mode, the placeholder
126128
// table itself: the user never saw it, so archive it back out of the
127129
// workspace (no hard-delete surface exists; archived is invisible).
128-
const { releaseJobClaim, deleteTable } = await import('@/lib/table/service')
129130
await releaseJobClaim(table.id, importId).catch(() => {})
130131
await deleteTable(table.id, requestId).catch(() => {})
131132
throw error

apps/sim/lib/execution/sandbox/bundles/docx.cjs

Lines changed: 39 additions & 24 deletions
Large diffs are not rendered by default.

apps/sim/lib/execution/sandbox/bundles/pdf-lib.cjs

Lines changed: 13 additions & 13 deletions
Large diffs are not rendered by default.

apps/sim/lib/uploads/core/setup.server.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@ import {
1212

1313
const logger = createLogger('UploadsSetup')
1414

15-
const PROJECT_ROOT = path.resolve(process.cwd())
16-
export const UPLOAD_DIR_SERVER = join(PROJECT_ROOT, 'uploads')
15+
// turbopackIgnore: an unscoped process.cwd() makes node-file-tracing sweep the whole
16+
// project (including next.config.ts) into every route graph that reaches this module.
17+
// Two routes doing so emit the swept config into same-named server chunks — when their
18+
// contents diverge, the build dies with "Two or more assets … same output path".
19+
const PROJECT_ROOT = path.resolve(/*turbopackIgnore: true*/ process.cwd())
20+
export const UPLOAD_DIR_SERVER = join(/*turbopackIgnore: true*/ PROJECT_ROOT, 'uploads')
1721

1822
/**
1923
* Server-only function to ensure uploads directory exists

0 commit comments

Comments
 (0)