Saltar al contenido

Expression.Error: cannot convert null en Power Query — todas las causas y fixes

Pantalla de Power Query mostrando Expression.Error cannot convert null to type Number con código M de solución

TL;DR: Este error aparece cuando Power Query intenta convertir un valor null a un tipo concreto (Number, List, Logical, Text) y no puede. La causa más común es operar con una columna que tiene nulos sin protegerla antes. El fix rápido es try [columna] otherwise 0 o un chequeo explícito if [col] <> null then [col] else 0. Existen 4 variantes del error según el tipo destino, y cada una tiene su causa específica.


No hemos podido validar tu suscripción.
Tu PDF va en camino — revisa tu correo

Tu guía de Power Query gratis

¿Por qué aparece este error?

En Power Query, null es un valor válido que significa «dato ausente». El problema ocurre cuando aplicás una operación que requiere un tipo específico —sumar, comparar, paginar— y la columna contiene null en alguna fila. Power Query no convierte null automáticamente: lanza el error en lugar de asumir un valor por defecto.

Con más de 300,000 consultas acumuladas en el foro oficial de Microsoft Fabric, es uno de los errores más frecuentes de Power Query.

Las cuatro variantes más comunes:

Error Cuándo aparece Causa típica
cannot convert null to type Number Operaciones aritméticas, comparaciones numéricas Columna numérica con nulos
cannot convert null to type Logical Condicionales if sobre columnas con nulos if [col] = "valor" sin chequear null primero
cannot convert null to type List Paginación de APIs, List.Generate URL dinámica que devuelve null en alguna página
cannot convert null to type Text GroupBy, concatenación de texto Columna de texto con nulos en agregación

¿Cómo diagnosticar dónde está el null?

Antes de aplicar cualquier fix, identificá el paso exacto que falla:

  1. En el editor de Power Query, mirá el panel Pasos aplicados — el paso marcado con el icono de error es el origen.
  2. Hacé clic en el paso anterior al que falla y revisá la columna involucrada.
  3. Filtrá por null en esa columna para confirmar que existen valores ausentes.

Un truco útil: agregá un paso intermedio temporal con Table.RowCount antes y después del paso problemático para ver si la cantidad de filas cambia inesperadamente — a veces el null aparece por una combinación de pasos, no por datos de origen.


Fix 1: Chequeo explícito con if

El más legible. Antes de operar con la columna, verificá que no sea null:

= Table.AddColumn(origen, "Resultado", each
    if [precio] <> null then [precio] * [cantidad]
    else 0
)

Cuándo usarlo: operaciones aritméticas sencillas sobre una o dos columnas.

Limitación: se vuelve verboso si hay muchas columnas involucradas.


Fix 2: try ... otherwise para cualquier expresión

El más flexible. Envuelve cualquier expresión y captura el error si el resultado es null o falla por cualquier razón:

= Table.AddColumn(origen, "Resultado", each
    try [precio] * [cantidad] otherwise 0
)

También funciona para el caso de null to type Logical en condicionales:

// En lugar de:
each if [fecha_inicio] > #date(2024,1,1) then "2024" else "anterior"

// Usar:
each try (if [fecha_inicio] > #date(2024,1,1) then "2024" else "anterior") otherwise "sin fecha"

Cuándo usarlo: cuando el origen del null no es predecible o la expresión es compleja.


Fix 3: Operador de fusión de null ??

El lenguaje M soporta el operador ?? (null coalescing) desde versiones recientes. Es la forma más concisa:

= Table.AddColumn(origen, "Resultado", each
    ([precio] ?? 0) * ([cantidad] ?? 1)
)

[precio] ?? 0 significa: «si [precio] es null, usá 0; si no, usá el valor».

Cuándo usarlo: reemplazo rápido de if x <> null then x else default. Más limpio que el if explícito cuando el default es un escalar simple.


Fix 4: Forzar el tipo de columna antes de operar

A veces el error aparece porque Power Query infiere el tipo de una columna como any y al operar descubre un null. Forzar el tipo antes resuelve el problema:

= Table.TransformColumnTypes(origen, {
    {"precio", type number},
    {"cantidad", type number}
})

Esto convierte los nulos a null tipado correctamente. Combinalo con un Table.ReplaceValue si querés reemplazar los nulos por cero antes de operar:

= Table.ReplaceValue(
    origen,
    null,
    0,
    Replacer.ReplaceValue,
    {"precio", "cantidad"}
)

Cuándo usarlo: cuando el error ocurre en múltiples columnas y preferís limpiar los nulos una sola vez en lugar de proteger cada expresión individualmente.


Fix 5: GroupBy con nulos en columnas de agregación

La variante cannot convert null to type Text o Number en GroupBy es especialmente frustrante porque el error no aparece en la columna de agrupación sino en la de agregación.

// Esto falla si hay nulos en [importe]:
= Table.Group(origen, {"cliente"}, {
    {"total", each List.Sum([importe]), type number}
})

// Fix: proteger la suma con try...otherwise
= Table.Group(origen, {"cliente"}, {
    {"total", each try List.Sum(List.Select([importe], each _ <> null)) otherwise 0, type number}
})

List.Select([importe], each _ <> null) filtra los nulos de la lista antes de sumar. try ... otherwise 0 protege el caso en que todos los valores sean nulos.


Fix 6: null to type List en paginación de APIs

Esta variante aparece al usar List.Generate con una URL dinámica para paginar resultados de una API. El problema es que Power Query no permite URLs completamente estáticas en Web.Contents cuando se usa en el servicio Power BI (restricción de seguridad).

// Función de página — URL debe ser estática en el primer argumento
let
    ObtenerPagina = (numeroPagina as number) =>
    let
        datos = Json.Document(
            Web.Contents(
                "https://api.ejemplo.com",  // URL base estática
                [
                    RelativePath = "/endpoint",
                    Query = [page = Number.ToText(numeroPagina), pageSize = "100"],
                    Headers = [Authorization = "Bearer " & token]
                ]
            )
        )
    in
        datos
in
    ObtenerPagina
// Query de paginación con protección de null
let
    paginas = List.Generate(
        () => [resultado = try ObtenerPagina(1) otherwise null, pagina = 1],
        each [resultado] <> null and List.Count([resultado]) > 0,
        each [
            resultado = try ObtenerPagina([pagina] + 1) otherwise null,
            pagina = [pagina] + 1
        ],
        each [resultado]
    )
in
    paginas

La clave es separar la URL base (estática) del path relativo y los parámetros de query.

Power BI: Power Query Limpiar y extraer Datos con Lenguaje MUdemy
Power Query

Power BI: Power Query Limpiar y extraer Datos con Lenguaje M

★ 4.6(1100 estudiantes)
$54.99

¿Cuándo aparece el error de forma inesperada tras un paso de filtrado?

Este es el caso más confuso: el error aparece en un paso que no toca la columna problemática. La causa es que Power Query re-evalúa los tipos de columna después de cada paso de transformación.

Si en el paso 16 tenés una columna numérica sin nulos, pero el paso 17 filtra filas basándose en otra columna, Power Query puede re-evaluar el tipo de la primera columna y encontrar nulos que «aparecieron» como efecto secundario del filtrado (filas que antes tenían valores ahora quedan con nulos por la lógica de merge o join).

La solución es añadir un paso de limpieza de nulos después del filtrado:

// Paso 17: tu filtro normal
= Table.SelectRows(anterior, each [fechaInicio] <= [fechaFin]),

// Paso 18: limpiar nulos en columnas críticas
= Table.ReplaceValue(anterior, null, 0, Replacer.ReplaceValue, {"importe", "cantidad"})

Cómo prevenir el error desde el diseño de la consulta

Regla general: tratá los nulos lo antes posible en el pipeline, no cuando ya son un problema.

  1. Paso de limpieza temprano: en los primeros pasos de cada consulta, añadí un Table.ReplaceValue para las columnas críticas.
  2. Tipado explícito: no dependas de la inferencia automática de tipos. Definí los tipos en un paso explícito con Table.TransformColumnTypes.
  3. Validación en columnas calculadas: usá ?? o try...otherwise en cada columna calculada nueva.
  4. Revisión en origen: si el sistema de origen permite nulos en columnas que no deberían tenerlos (importe, cantidad, ID), el problema real está en los datos. Consultá con el equipo de datos.

Resumen de fixes por variante

Variante del error Fix recomendado Alternativa
null to type Number ([col] ?? 0) * ... try ... otherwise 0
null to type Logical try (if [col] = x ...) otherwise "default" if [col] <> null and [col] = x
null to type List URL base estática + RelativePath dinámico try ObtenerPagina(n) otherwise null
null to type Text List.Select([col], each _ <> null) en GroupBy Table.ReplaceValue antes del GroupBy
Error en paso posterior Table.ReplaceValue después del filtro Table.TransformColumnTypes forzado

Preguntas frecuentes

¿Por qué el error aparece en un paso que no tiene nulos visibles? Power Query evalúa las columnas de forma lazy (perezosa). Un paso que filtra filas puede exponer nulos en otras columnas que antes estaban «cubiertos» por las filas filtradas. Añadí un paso de limpieza de nulos después de cualquier filtro o join.

¿try...otherwise es más lento que el if explícito? En conjuntos de datos pequeños la diferencia es imperceptible. En tablas de millones de filas, el if [col] <> null then ... else ... es marginalmente más rápido porque no usa el mecanismo de manejo de errores de M. Para la mayoría de los casos, ?? es la mejor combinación de legibilidad y rendimiento.

¿Puedo reemplazar todos los nulos del modelo de una vez? No en Power Query de forma global, pero sí por tabla. El Table.ReplaceValue con Replacer.ReplaceValue acepta una lista de columnas. Para reemplazar en todas las columnas numéricas de una tabla:

= Table.ReplaceValue(
    origen,
    null,
    0,
    Replacer.ReplaceValue,
    List.Select(Table.ColumnNames(origen),
        each Table.Schema(origen){[Name=_]}[Kind] = "number")
)
Power BI: Power Query Limpiar y extraer Datos con Lenguaje MUdemy
Power Query

Power BI: Power Query Limpiar y extraer Datos con Lenguaje M

★ 4.6(1100 estudiantes)
$54.99

Comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *