Setting the file. One moment.
Subchapter 4.24
references/migrations/minikit-to-farcaster/pitfalls.mdMarkdown4 KBView on GitHub
Accessing sdk.context without awaiting.
// WRONG
const fid = sdk.context?.user?.fid;
// CORRECT
const context = await sdk.context;
const fid = context?.user?.fid;Passing parameters to sdk.isInMiniApp().
// WRONG
await sdk.isInMiniApp({ timeoutMs: 500 });
// CORRECT
await sdk.isInMiniApp();Custom timeout workaround:
const checkWithTimeout = async (ms = 5000) => {
try {
return await Promise.race([
sdk.isInMiniApp(),
new Promise((_, r) => setTimeout(() => r(new Error('Timeout')), ms))
]);
} catch {
return false;
}
};Assigning sdk.context to state without awaiting.
// WRONG
const context = sdk.context;
setFrameContext({ context, isInMiniApp: true });
// CORRECT
const context = await sdk.context;
setFrameContext({ context, isInMiniApp: true });setPrimaryButton no longer supports callbacks.
// WRONG (MiniKit pattern)
usePrimaryButton(
{ text: "Click" },
() => handleClick()
);
// CORRECT - state only, no callback
await sdk.actions.setPrimaryButton({
text: "Click",
disabled: false,
hidden: false,
loading: false
});For click handling, use regular React buttons.
Possible causes:
'use client' directiveFrameProvider not in provider chain.
// WRONG
export function Providers({ children }) {
return <WagmiProvider>{children}</WagmiProvider>;
}
// CORRECT
export function Providers({ children }) {
return (
<FrameProvider>
<WagmiProvider>{children}</WagmiProvider>
</FrameProvider>
);
}Not awaiting sdk.context:
// WRONG
const context = sdk.context; // Promise, not data
// CORRECT
const context = await sdk.context;// WRONG - returns Promise
useEffect(async () => {
await sdk.actions.ready();
}, []);
// CORRECT - wrap in function
useEffect(() => {
const init = async () => {
await sdk.actions.ready();
};
init();
}, []);function MyComponent() {
const [context, setContext] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const load = async () => {
try {
const isInMiniApp = await sdk.isInMiniApp();
if (isInMiniApp) {
const ctx = await sdk.context;
setContext(ctx);
}
} finally {
setLoading(false);
}
};
load();
}, []);
if (loading) return null;
return <div>{context?.user?.fid}</div>;
}signIn returns SignInResult, not boolean.
// WRONG (MiniKit pattern)
const result = await signIn({ nonce });
if (result === false) { ... }
// CORRECT
const result = await sdk.actions.signIn({ nonce });
if (!result) {
// Sign-in cancelled or failed
}For SDK v0.2.0+, prefer Quick Auth:
const { token } = await sdk.quickAuth.getToken();
// Or use authenticated fetch
const res = await sdk.quickAuth.fetch('/api/auth');After conversion, verify:
# No MiniKit imports remaining
grep -r "@coinbase/onchainkit/minikit" src/
# Check sdk.context usage (should be awaited)
grep -r "sdk\.context" src/
# Check isInMiniApp calls (no parameters)
grep -r "isInMiniApp(" src/
# Build and type check
npm run build && npx tsc --noEmit