fix(v2): envio-digest insert nodes were missing the required columns mapping

Found running the real Slack test send (with the user's explicit
confirmation to try SEND_ENABLED=true once): the Slack node itself fired
correctly and got a real response back from Slack's API ("invalid_arguments"
-- confirms the pipeline mechanics, credential and node config work end
to end up to that point). Separately, once the failure branch tried to
record it, "Data Table - Registrar Envio Digest (Falha)" crashed with
"Cannot convert undefined or null to object" inside n8n's own insert
operation -- both new envio-digest insert nodes had operation:"insert"
and dataTableId but no "columns" mapping, which is a required property
for insert/update/upsert (confirmed via get_node nodes-base.dataTable).
Fixed both nodes with the same columns.mappingMode:"defineBelow" shape
already used by the existing "Data Table - Registrar Shadow Run" node.

Added a regression test scanning every dataTable node with an insert/
update/upsert operation for a columns.mappingMode.

158/158 tests passing.

Separately (not fixed here, needs the user): the actual Slack
"invalid_arguments" error suggests $vars.SLACK_CHANNEL_TECNICO isn't
resolving to a valid channel on this n8n instance -- no tool available
to this agent can list/inspect n8n instance Variables to confirm. Left
SEND_ENABLED=false and the workflow inactive pending the user's input on
the correct channel.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Gustavo
2026-08-24 21:02:05 -03:00
co-authored by Claude Sonnet 5
parent 86039ecfe4
commit 617c67493f
3 changed files with 65 additions and 0 deletions
+24
View File
@@ -850,6 +850,18 @@
"dataTableId": {
"mode": "name",
"value": "coordenador_glpi_envios_digest"
},
"resource": "row",
"columns": {
"mappingMode": "defineBelow",
"value": {
"report_date": "={{ $json.report_date }}",
"run_type": "={{ $json.run_type }}",
"message_hash": "={{ $json.message_hash }}",
"sent_at": "={{ $json.sent_at }}",
"status": "={{ $json.status }}",
"error_detail": "={{ $json.error_detail }}"
}
}
}
},
@@ -867,6 +879,18 @@
"dataTableId": {
"mode": "name",
"value": "coordenador_glpi_envios_digest"
},
"resource": "row",
"columns": {
"mappingMode": "defineBelow",
"value": {
"report_date": "={{ $json.report_date }}",
"run_type": "={{ $json.run_type }}",
"message_hash": "={{ $json.message_hash }}",
"sent_at": "={{ $json.sent_at }}",
"status": "={{ $json.status }}",
"error_detail": "={{ $json.error_detail }}"
}
}
}
},
+24
View File
@@ -850,6 +850,18 @@
"dataTableId": {
"mode": "name",
"value": "coordenador_glpi_envios_digest"
},
"resource": "row",
"columns": {
"mappingMode": "defineBelow",
"value": {
"report_date": "={{ $json.report_date }}",
"run_type": "={{ $json.run_type }}",
"message_hash": "={{ $json.message_hash }}",
"sent_at": "={{ $json.sent_at }}",
"status": "={{ $json.status }}",
"error_detail": "={{ $json.error_detail }}"
}
}
}
},
@@ -867,6 +879,18 @@
"dataTableId": {
"mode": "name",
"value": "coordenador_glpi_envios_digest"
},
"resource": "row",
"columns": {
"mappingMode": "defineBelow",
"value": {
"report_date": "={{ $json.report_date }}",
"run_type": "={{ $json.run_type }}",
"message_hash": "={{ $json.message_hash }}",
"sent_at": "={{ $json.sent_at }}",
"status": "={{ $json.status }}",
"error_detail": "={{ $json.error_detail }}"
}
}
}
},
+17
View File
@@ -181,6 +181,23 @@ test('nodes n8n-nodes-base.dataTable usam valores de operation validos (bug real
}
});
test('todo node dataTable com operation insert/update/upsert tem columns.mappingMode definido (bug real: insert sem columns crasha no n8n com "Cannot convert undefined or null to object")', () => {
// Regressao: rodou de verdade contra o DEV -- os dois nodes novos "Data Table - Registrar
// Envio Digest (Sucesso/Falha)" tinham operation:"insert" e dataTableId, mas nenhum
// "columns" -- que e um campo OBRIGATORIO pra insert/update/upsert (ver get_node
// nodes-base.dataTable). Sem ele, o proprio node do n8n crasha dentro do proprio insert.
const wf = buildWorkflow();
const OPERATIONS_REQUIRING_COLUMNS = new Set(['insert', 'update', 'upsert']);
for (const node of wf.nodes) {
if (node.type !== 'n8n-nodes-base.dataTable') continue;
if (!OPERATIONS_REQUIRING_COLUMNS.has(node.parameters.operation)) continue;
assert.ok(
node.parameters.columns && node.parameters.columns.mappingMode,
`node "${node.name}" tem operation="${node.parameters.operation}" mas nao tem columns.mappingMode -- vai crashar em runtime`,
);
}
});
test('registro de envio (per-ticket) so acontece depois do Data Table de sucesso do Slack -- nunca antes da confirmacao', () => {
const wf = buildWorkflow();
// "Code - Selecionar Top 10" nao pode mais alimentar "Code - Preparar Registro de Envio" direto.