[SDK] TranscriptStore ENOENT on Vercel serverless despite JsonlLocalAgentStore in /tmp

Where does the bug appear (feature/product)?

Cursor SDK

Describe the Bug

@cursor/sdk (1.0.28) local agent on Vercel serverless logs:

[TranscriptStore] Failed to write transcript: Error: ENOENT: no such file or directory, mkdir ‘/home/sbx_user1051’

We pass local.store: JsonlLocalAgentStore under mkdtemp in /tmp and a sealed cwd per the TypeScript SDK docs. Kernel runs still complete and return tool outcomes, but TranscriptStore appears to write under $HOME, which does not exist in the Vercel sandbox.

Steps to Reproduce

  1. Deploy a SvelteKit (Node) API route on Vercel Preview that runs one @cursor/sdk local agent per POST.
  2. Agent.create with model composer-2.5, tools: [‘mcp’], disallowedTools: [‘task’].
  3. local.cwd = mkdtemp under os.tmpdir(); local.store = new JsonlLocalAgentStore(path.join(cwd, ‘store’)); settingSources: .
  4. agent.send(utterance) → run.wait() → dispose agent; rm cwd in finally.
  5. Call the route from a client (e.g. mobile browser on Preview URL).
  6. Check Vercel function logs for the TranscriptStore ENOENT line.

Expected Behavior

No filesystem errors in logs. Transcript persistence (if any) should use the configured local.store path under /tmp, or skip transcript writes on serverless when $HOME is not writable. Kernel behavior should be unchanged.

Operating System

Linux

Version Information

@cursor/sdk: 1.0.28
Host: Vercel serverless Node (Preview, develop branch)
App: SvelteKit 2 + @sveltejs/adapter-vercel
Node (project engines): >=24.0.0
Not using Cursor IDE for this path; server-side SDK only.

For AI issues: which model did you use?

composer-2.5 (via Agent.create model: { id: ‘composer-2.5’ })

For AI issues: add Request ID with privacy disabled

N/A — server-side @cursor/sdk in our own API route, not the Cursor IDE chat. We did not capture a requestId from the SDK run result. Can provide Vercel deployment ID / function invocation timestamp if needed.

Additional Information

Docs followed: Cursor TypeScript SDK | Cursor Documentation (JsonlLocalAgentStore for environments where default SQLite store path is unavailable).

Relevant Agent.create shape:

  • local.cwd: sealed temp dir under os.tmpdir()
  • local.store: JsonlLocalAgentStore(/store)
  • local.settingSources:
  • local.customTools: allowlisted tools only

Error path: mkdir ‘/home/sbx_user1051’ — looks like sandbox $HOME on Vercel, not our store path.

Impact: noisy logs every kernel request; product still works (refuse/clarify/draft/render). Unsure if transcript data is lost.

Planned workaround: HOME=/tmp on Vercel env (not tested yet).

Repo is private; happy to share a minimal repro snippet if useful.

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey, thanks for the detailed report, you got it right.

Transcript files are a separate local debug mirror, and the path is resolved from $HOME, not from your configured local.store. On Vercel there’s no home directory, so the write fails with ENOENT. The errors are caught and logged, so this doesn’t affect runs. The agent state is persisted via your JsonlLocalAgentStore in /tmp. Only the transcript mirror isn’t written. Run data isn’t lost.

To remove the log noise, set the CURSOR_DATA_DIR env var to a writable path, for example CURSOR_DATA_DIR=/tmp/cursor-data in your Vercel project settings. The SDK will put the transcript mirror and other local data there. Your HOME=/tmp option will also work, but CURSOR_DATA_DIR is more targeted since it only affects Cursor data.

The behavior itself, where the mirror ignores local.store and is hard tied to $HOME, is not how it should work in homeless serverless environments. I’ve passed this to the team so the SDK handles these cases more gracefully out of the box. If there’s an update, I’ll post it here. Let me know if the workaround helped.

Hey Dean! Thank you for the quick response. The variable CURSOR_DATA_DIR=/tmp/cursor-data in Vercel turned off the warning log! Will keep it like that and really glad if you update me with any news.

Just in case it is useful, I found another related warning that maybe you can pass to the team: on Vercel build, @sveltejs/adapter-vercel warns about unresolved @cursor/sdk deps (bun:sqlite, vendor/cursor-sdk-shared/*.ts). Build succeeds; runtime seems fine with ssr.external.

Hope it helps making this sdk greater! Thanks again, kind regards.

Andy.-

Great, glad CURSOR_DATA_DIR removed the noise. I’d keep it that way.

On the second point, those build warnings are expected bundler noise and not an issue. The SDK only references bun:sqlite in a Bun environment, and the internal vendor/cursor-sdk-shared/*.ts files are pulled in conditionally. When @sveltejs/adapter-vercel (Vite/Rollup) builds for Node, it sees those imports and can’t resolve them statically, which is why you get warnings. If the build succeeds and runtime works, it’s safe to ignore. The ssr.external you already added is exactly the right way to keep them out of the bundle.

I’ve shared this with the SDK team. We should make the out of the box experience cleaner for bundlers in serverless setups. If I get an update on the main issue (transcript mirror), I’ll post it here. Thanks for the detailed follow-up, Andy.