agentsclimarketplace

Error detective

Skill felipeArnold/filament-ai-skills/skills/error-detective

Agente especializado em detectar, diagnosticar e corrigir erros no sistema. Analisa logs, browser console, exceções PHP, erros de banco de dados, erros Livewire/Filament e problemas de configuração. Ativa quando o usuário menciona: erro, exception, bug, falha, não funciona, quebrou, 500, 404, null, undefined, stack trace, log, error, crash, problema, não atualiza, não salva, tela branca.From its SKILL.md

Install
npx -y skills add felipeArnold/filament-ai-skills --skill error-detective

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

8.9 KB, as published. Nobody here has run it

Error Detective — Diagnóstico de Erros do Sistema

Objetivo

Localizar, diagnosticar e corrigir erros no sistema de forma sistemática. Nunca pule etapas — leia os logs reais antes de sugerir correções.


Protocolo de Diagnóstico (5 Etapas)

Etapa 1 — Coletar evidências

Execute em paralelo:

# Últimas linhas do log Laravel
tail -n 100 storage/logs/laravel.log

# Logs do Horizon (se jobs envolvidos)
php artisan horizon:status

Usando as ferramentas MCP disponíveis:

  • browser-logs — capturar erros do console do browser
  • tinker — executar PHP para testar código suspeito
  • database-query — verificar estado dos dados no banco

Etapa 2 — Classificar o erro

TipoSintomasOnde investigar
PHP ExceptionStack trace no logstorage/logs/laravel.log
Livewire/FilamentErro no console, ação sem respostabrowser-logs + log Laravel
Banco de dadosSQLSTATE, constraint violationLog Laravel + database-query
Null safeErrorException: Attempt to read property on nullCódigo + migration para verificar nullable
Filament pathTotal não atualiza em RepeaterVer guideline repeater-calculations.md
N+1Timeout, lentidão extremaTelescope ou log de queries
Fila/JobDados não processados, status presophp artisan horizon:status + log
Permissão403, acesso negadoPolicy + UserRole enum
FrontendCSS/JS não atualizadonpm run build ou npm run dev
MySQL GROUP BYSQLSTATE[42000] only_full_group_by em Filament widgetVer erro #9 — subquery wrapper

Etapa 3 — Localizar o código

Para cada erro identificado:

# Buscar por padrão de código suspeito
grep -rn "NomeDoMetodo\|NomeDaClasse" app/

# Verificar arquivo específico da stack trace
# Linha exata apontada pelo stack trace é o ponto de partida

Ferramentas:

  • Grep — buscar padrão no código
  • Read — ler arquivo com contexto da linha do erro
  • tinker — reproduzir o erro isoladamente

Etapa 4 — Diagnosticar causa raiz

Não corrija sintomas. Identifique a causa raiz antes.

Perguntas-guia:

  1. O erro acontece sempre ou em condições específicas? (dados específicos, usuário, tenant)
  2. Quando começou? (correlacionar com commits recentes)
  3. Há relação com nullable FK? (verificar migration)
  4. O dado existe no banco? (database-query)
  5. É um problema de estado Livewire? (re-render, hydration)

Etapa 5 — Corrigir e verificar

  1. Aplicar correção mínima e focada
  2. Executar testes relacionados: php artisan test --compact --filter=NomeDoTest
  3. Verificar logs após correção
  4. vendor/bin/pint --dirty antes de commitar

Erros Mais Comuns neste Projeto

1. Repeater total não atualiza ao deletar item

Causa: afterStateUpdated do Repeater usa paths ../../campo mas o $get já está no nível root.

Solução: Ver guideline repeater-calculations.md — passar prefix: '' para o Repeater.

->afterStateUpdated(function ($get, $set): void {
    self::recalculateTotals($get, $set, ''); // '' para nível root
})

2. ErrorException: Attempt to read property on null

Causa: Acesso a relação nullable sem ?->.

Diagnóstico:

# Verificar se FK é nullable na migration
grep -n "nullable\|->foreign" database/migrations/*_create_table.php

Solução:

// ERRADO
$record->person->name

// CORRETO (FK nullable)
$record->person?->name

3. Formatação monetária retornando valor errado

Causa: O valor não foi convertido de string pt-BR (com vírgula) para float antes de formatar.

Solução:

use Illuminate\Support\Number;

// ERRADO — passa string pt-BR direto para Number::currency()
$set('total', Number::currency((float) $get('unit_price'), 'BRL'));

// CORRETO — converte para decimal primeiro
$unitPrice = (float) str_replace(['.', ','], ['', '.'], $get('unit_price'));
$set('total', Number::currency($unitPrice * $qty, 'BRL'));

4. Multi-tenancy: dados de outro tenant visíveis

Causa: Query sem escopo de tenant.

Diagnóstico:

// tinker
Tenant::find($tenantId)->orders()->count();
Order::where('tenant_id', $tenantId)->count();

Solução: Verificar se o model tem global scope ou se o resource usa ->modifyQueryUsing().

5. Action não executa / modal fecha sem ação

Causa: Falta de parent::setUp() em setUp(), ou ->action() não configurado.

Solução:

protected function setUp(): void
{
    parent::setUp(); // OBRIGATÓRIO como primeira linha
    $this->action(fn (array $data) => $this->execute($data));
}

6. Namespace errado em Filament v5

Causa: Confundir namespaces de Form fields, Layout e Infolist.

TipoNamespace correto
Form fields (TextInput, Select)Filament\Forms\Components\
Layout (Section, Grid, Tabs)Filament\Schemas\Components\
Infolist entries (TextEntry)Filament\Infolists\Components\
ActionsFilament\Actions\
Schema methodFilament\Schemas\Schema
Get/Set utilitiesFilament\Schemas\Components\Utilities\

7. Job preso / não processado

Diagnóstico:

php artisan horizon:status
php artisan queue:failed
php artisan queue:failed --queue=nome_da_fila

Solução:

# Tentar re-executar
php artisan queue:retry all

# Ver detalhes do job falhado
php artisan queue:failed-table

8. Vite/Frontend não atualiza

Sintoma: CSS ou JS não reflete mudanças.

Solução: Pedir ao usuário para executar npm run build ou npm run dev.

9. SQLSTATE[42000]: only_full_group_by — Filament TableWidget com GROUP BY

Causa: Filament TableWidget adiciona automaticamente ORDER BY tabela.id ASC como tiebreaker de paginação. Em MySQL com only_full_group_by, esse id não está no GROUP BY nem é um agregado — query rejeitada.

Sintoma típico no erro:

SQLSTATE[42000]: ... Expression #2 of ORDER BY clause is not in GROUP BY clause
... order by total_revenue desc, profitability_items.id asc

Diagnóstico: A query usa ->groupBy(...) + ->orderByDesc(...), e Filament appenda ORDER BY model.id.

Solução: Envolver a query agrupada em uma subquery com o mesmo alias da tabela. O Filament aplica seus sorts na query externa (sem GROUP BY), tornando-a compatível com only_full_group_by:

protected function getTableQuery(): Builder
{
    $subQuery = MyModel::query()
        ->selectRaw('
            grouped_col as id,   // alias id = coluna agrupada
            grouped_col,
            SUM(value) as total,
            ...
        ')
        ->where(...)
        ->groupBy('grouped_col', 'item_name')
        ->orderByDesc('total')
        ->limit(10);

    // Outer query: Filament aplica ORDER BY mymodels.id aqui,
    // que referencia o 'id' do subquery (= grouped_col) — válido
    return MyModel::query()
        ->fromSub($subQuery, 'mymodels')  // alias = nome da tabela do model
        ->orderByDesc('total');
}

Regras:

  • O alias do fromSub() deve ser exatamente o nome da tabela do model (ex: profitability_items)
  • Manter o ->orderByDesc() na query externa para que o sort do Filament seja tiebreaker, não o sort primário
  • O ->limit() deve ficar no subquery (garante os top N antes do Filament reordenar)

Busca Específica por Tipo de Erro

Erros de null-safe em produção

grep -n "Attempt to read property\|Call to a member function.*on null" storage/logs/laravel.log | tail -20

Queries lentas / N+1

grep -n "select \*\|N+1\|QueryException" storage/logs/laravel.log | tail -20

Erros de validação Filament

grep -n "ValidationException\|validation.required\|validation.unique" storage/logs/laravel.log | tail -20

Erros de autorização

grep -n "AuthorizationException\|403\|This action is unauthorized" storage/logs/laravel.log | tail -20

Relatório de Diagnóstico

Ao concluir, gerar:

## Diagnóstico: [Descrição do Erro]

### Evidências Coletadas
- Log: [linha relevante]
- Browser: [erro do console se houver]
- Banco: [estado dos dados]

### Causa Raiz
[Explicação técnica da causa]

### Correção Aplicada
- Arquivo: [path:linha]
- Mudança: [descrição]

### Verificação
- [ ] Testes executados: `php artisan test --compact --filter=...`
- [ ] Logs verificados após correção
- [ ] Pint executado: `vendor/bin/pint --dirty`

Keep looking

Skills are one crate of 626,474. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.