# Erro: Invalid state format
> **⚠️ ATUALIZAÇÃO:** Este erro foi resolvido com uma nova abordagem. Veja [fluxo-final-google-oauth.md](./fluxo-final-google-oauth.md) para a solução final.
---
## O Problema
Quando tentamos conectar Google Calendar, o n8n retornou:
```html
Error: Invalid state format
```
## Causa Raiz
O dashboard estava enviando `user_id` no parâmetro `state`:
```typescript
const state = user.id; // ❌ ERRADO - UUID do user
```
Mas o **n8n espera receber o `credential_id`** no state:
```typescript
const state = n8nCredentialId; // ✅ CORRETO - ID da credencial n8n
```
## Por que isso acontece?
O n8n usa o `state` para identificar **qual credencial** deve ser atualizada com os tokens OAuth.
Quando o Google redireciona de volta para:
```
https://n8n.automatizase.com.br/rest/oauth2-credential/callback?code=...&state=...
```
O n8n:
1. Lê o `state`
2. Procura a credencial com esse ID
3. Atualiza a credencial com os tokens OAuth
Se o `state` não for um `credential_id` válido do n8n, ele retorna "Invalid state format".
## Solução
### 1. Usar credential_id no state
**Dashboard (`app/dashboard/page.tsx`):**
```typescript
const n8nCredentialId = process.env.NEXT_PUBLIC_N8N_CREDENTIAL_ID;
const state = n8nCredentialId; // ID da credencial n8n
```
### 2. Pegar user_id da sessão no callback
**Callback (`app/api/google-calendar/callback/route.ts`):**
```typescript
// Criar cliente Supabase com cookies
const cookieStore = await cookies();
const supabase = createServerClient(..., {
cookies: { ... }
});
// Pegar user da sessão
const { data: { user } } = await supabase.auth.getUser();
// Salvar no banco usando user.id (não o state)
await supabase.schema("portal").from("integrations").upsert({
user_id: user.id,
provider: "google_calendar",
status: "connecting",
...
});
```
## Fluxo Correto
```
1. Dashboard:
state = credential_id (ex: "ccTThTS9TKsejR7W")
2. Google OAuth:
Redireciona com state=credential_id
3. Callback Dashboard:
- Lê state (credential_id)
- Lê user_id da sessão Supabase
- Salva no banco: user_id + status
- Redireciona para n8n com state=credential_id
4. n8n:
- Lê state (credential_id)
- Atualiza credencial com tokens OAuth
- Sucesso!
```
## Variáveis de Ambiente Necessárias
```bash
# Google OAuth
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
# n8n Credential ID (IMPORTANTE!)
NEXT_PUBLIC_N8N_CREDENTIAL_ID=ccTThTS9TKsejR7W
# n8n Base URL
N8N_BASE_URL=https://n8n.automatizase.com.br
```
## Como encontrar o Credential ID?
### Opção 1: URL do n8n
1. Acesse n8n → Credentials
2. Clique na credencial Google Calendar OAuth2
3. URL será: `https://n8n.automatizase.com.br/credentials/ccTThTS9TKsejR7W`
4. O ID é a última parte: `ccTThTS9TKsejR7W`
### Opção 2: API do n8n
```bash
curl https://n8n.automatizase.com.br/api/v1/credentials \
-H "X-N8N-API-KEY: your-api-key" | jq '.[] | select(.type == "googleCalendarOAuth2Api") | .id'
```
## Resumo
- ❌ **ERRADO:** `state = user_id` (UUID)
- ✅ **CORRETO:** `state = credential_id` (ID do n8n)
- ✅ **user_id:** Pegar da sessão Supabase no callback
O `state` é para o **n8n identificar a credencial**.
O `user_id` é para o **dashboard salvar no banco**.