search
next

How to Fix Cookies can only be modified in a Server Action error

Quick fix for 'Cookies can only be modified in a Server Action' error in Next.js. Learn how to properly handle cookies in Next.js App Router.

person By Gautam Sharma
calendar_today January 8, 2026
schedule 3 min read
Next.js Cookies Server Actions Error Fix Authentication

The ‘Cookies can only be modified in a Server Action’ error occurs in Next.js when trying to modify cookies directly in client components or server components that aren’t server actions, which is not allowed in the App Router.


How the Error Happens

❌ Error Scenario:

// ❌ This causes the error
// components/ClientComponent.js
'use client';

import { cookies } from 'next/headers';

export default function CookieSetter() {
  const setCookie = () => {
    // ❌ Trying to modify cookies in client component
    cookies().set('theme', 'dark'); // ❌ Error: Can only be modified in Server Action
  };

  return <button onClick={setCookie}>Set Theme</button>;
}

// ✅ Create server action to modify cookies
// lib/actions.js
'use server';

import { cookies } from 'next/headers';

export async function setThemeCookie(theme) {
  // ✅ Modifying cookies in server action
  cookies().set('theme', theme, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    maxAge: 60 * 60 * 24 * 7, // 1 week
    path: '/',
  });
}

export async function clearThemeCookie() {
  cookies().delete('theme');
}
// ✅ Use server action in client component
// components/ThemeSelector.js
'use client';

import { setThemeCookie } from '../lib/actions';

export default function ThemeSelector() {
  const handleThemeChange = async (theme) => {
    // ✅ Call server action to set cookie
    await setThemeCookie(theme);
    // ✅ Refresh the page or update UI as needed
    window.location.reload();
  };

  return (
    <div>
      <button onClick={() => handleThemeChange('light')}>Light Theme</button>
      <button onClick={() => handleThemeChange('dark')}>Dark Theme</button>
    </div>
  );
}
// ✅ In app/api/cookie/route.js
import { NextResponse } from 'next/server';

export async function POST(request) {
  const { name, value } = await request.json();
  
  const response = NextResponse.json({ success: true });
  
  // ✅ Set cookie in route handler
  response.cookies.set(name, value, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    maxAge: 60 * 60 * 24 * 7,
    path: '/',
  });
  
  return response;
}
// ✅ Call the API route from client component
// components/CookieSetter.js
'use client';

export default function CookieSetter() {
  const setCookie = async () => {
    await fetch('/api/cookie', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name: 'theme', value: 'dark' }),
    });
  };

  return <button onClick={setCookie}>Set Theme</button>;
}

Solution 3: Read Cookies in Server Components

// ✅ Reading cookies is allowed in server components
// app/page.js
import { cookies } from 'next/headers';

export default function HomePage() {
  // ✅ Reading cookies is OK in server components
  const theme = cookies().get('theme')?.value || 'light';
  
  return (
    <div className={theme === 'dark' ? 'dark' : ''}>
      <h1>Current theme: {theme}</h1>
      {/* ✅ Pass theme to client component */}
      <ThemeSelector currentTheme={theme} />
    </div>
  );
}
// ✅ For client-only cookies, use browser storage
// components/ClientCookieManager.js
'use client';

import { useState, useEffect } from 'react';

export default function ClientCookieManager() {
  const [theme, setTheme] = useState('light');

  useEffect(() => {
    // ✅ Read from localStorage instead of cookies
    const savedTheme = localStorage.getItem('theme') || 'light';
    setTheme(savedTheme);
  }, []);

  const updateTheme = (newTheme) => {
    // ✅ Update localStorage instead of cookies
    localStorage.setItem('theme', newTheme);
    setTheme(newTheme);
    
    // ✅ Apply theme to document
    document.documentElement.classList.toggle('dark', newTheme === 'dark');
  };

  return (
    <div>
      <button onClick={() => updateTheme('light')}>Light</button>
      <button onClick={() => updateTheme('dark')}>Dark</button>
    </div>
  );
}
Gautam Sharma

About Gautam Sharma

Full-stack developer and tech blogger sharing coding tutorials and best practices

Related Articles

next

How to Solve Error: NEXT_REDIRECT error

Quick fix for 'Error: NEXT_REDIRECT' error in Next.js. Learn how to properly handle redirects in Next.js applications.

January 8, 2026
next

Fix: Middleware not running in Next.js error

Quick fix for middleware not running in Next.js. Learn how to properly configure and troubleshoot Next.js middleware.

January 8, 2026
next

Fix: Next.js App Router API route not working error

Quick fix for Next.js App Router API route not working error. Learn how to properly create and use API routes in the App Router.

January 8, 2026