Skip to content

Get Data Table Row / Row Found / Row Not Found

At a glance

Lives on: Data Table Function Library, with a Blueprint-specific typed node · Input: a Data Table reference and Row Name (Name) · Returns: a copy of that table's row struct through Out Row · Normal failure: a missing key runs Row Not Found; an invalid table/type is an authoring error that can also produce diagnostics · Side effects: none - it reads the table but does not edit, load, spawn, save, or cache anything · Official pages: Get Data Table Row, Data Driven Gameplay Elements, and UDataTable

The one-minute version

  • A Data Table stores many entries with one shared struct type. Each entry is addressed by a Name key called its row name.
  • Get Data Table Row asks one valid table for one row name. A match copies that row into Out Row and runs Row Found; an absent key runs Row Not Found.
  • The output starts as a wildcard because different tables use different row structs. Selecting DT_Items makes it an FItemRow; selecting DT_Enemies makes it an FEnemyRow.
  • Row Not Found is normal control flow for an optional or external ID. Do not read Out Row there: the node only promises a row on Row Found.
  • A variable that is typed as Data Table can still be None. A row name can also be empty, misspelled, renamed, or absent after reimport.
  • It does not search every table, choose a fallback row, create a row, or keep the result updated when the asset changes.

What it actually does

A Data Table has one UScriptStruct that describes every row and a map whose keys are FName row names. Given a table and a key, the node performs one dictionary-style lookup and copies the matching struct value to Blueprint.

For this table:

DT_Items uses FItemRow

Row Name        Display Name      Max Stack      Weight
Potion_Small    Small Potion      10             0.25
Key_Bronze      Bronze Key        1              0.05

this graph returns an FItemRow, not a generic Data Table object:

Get Data Table Row
    Data Table = DT_Items
    Row Name   = Potion_Small

Row Found
-> Out Row is a copy of DT_Items[Potion_Small]

Row Not Found
-> no valid row was produced

The engine behavior is approximately:

pseudocode - not engine source

function GetDataTableRow(Table, RowName, ExpectedRowStruct):
    if Table is None:
        report invalid Data Table input
        return FAILURE

    if Table.RowStruct is not compatible with ExpectedRowStruct:
        report a Blueprint type/validation problem
        return NOT_FOUND

    StoredRow = Table.RowMap.Find(RowName)
    if StoredRow does not exist:
        return NOT_FOUND

    OutRow = copy StoredRow using Table.RowStruct
    return FOUND

The copy matters. Changing the Blueprint struct variable afterward does not edit the Data Table asset. Likewise, changing or reimporting the table does not silently refresh a row value that gameplay copied earlier.

Why the output pin changes type

Epic's reference describes Out Row as a wildcard, but a wildcard is only the editor's unresolved starting state. The node must know one concrete struct before the Blueprint compiles.

The editor can infer that struct in two common ways:

  1. Select a literal Data Table asset on the node. The asset carries its row struct, so the output changes to that type.
  2. Connect Out Row to a known struct pin. A Data Table variable used at runtime must still contain a table with a compatible row struct.

Do not use one variable to swap freely between unrelated tables. A graph whose output is FItemRow cannot safely receive FEnemyRow merely because both inputs are Data Table references.

Changing a table's row struct later is a schema change. Reopen affected Blueprints, refresh or reconstruct stale nodes if needed, reconnect changed fields, compile, and inspect every row after reimport. New fields may receive defaults; renamed or removed fields do not migrate gameplay meaning for you.

When it fails (and what failure does)

The row name is absent

This is the ordinary failure:

ItemId = Potion_Large
DT_Items contains only Potion_Small and Key_Bronze
-> Row Not Found

The node does not invent a default row or choose the first row. Missing-row lookup is safe to branch on, and it does not modify the table. Treat any log or editor diagnostic as debugging help, not as the flow-control contract.

The Data Table reference is None

A Data Table variable needs an assigned asset just like any other object reference. An empty table input cannot produce a row and can produce a Blueprint compiler/runtime diagnostic. Treat that as invalid configuration, not as an optional missing-key case whose Row Not Found path replaces input validation. Validate required table references during setup instead of letting every lookup rediscover the mistake.

The row struct is incompatible

The selected table and the typed output must agree. Literal table assets let the editor catch most mismatches while compiling. Dynamic Data Table variables can move the mistake to runtime, so constrain them to tables that share the same row struct.

Import or reimport changed the keys

For CSV import, Epic's format uses a key field (normally the first column, commonly named Name). JSON can also use an explicit import key field. Those keys become row names.

UDataTable stores rows in a map, so two duplicate keys cannot survive as two separately addressable rows. Treat duplicate-key import diagnostics as broken source data; never depend on which duplicate an import path happens to keep. Renaming a key is also a breaking identity change: old lookups take Row Not Found until callers migrate.

The table is unavailable in a packaged build

A literal or serialized hard reference normally gives the cooker a dependency to follow. A table discovered only from a path assembled at runtime may not be discoverable during cooking. Test a packaged build and use Asset Manager or explicit cook rules when content is selected indirectly.

The lookup algorithm is not editor-only. If a cooked table and row exist, the same row-name lookup works in the packaged game.

The pattern everyone actually uses

Keep a durable ID in runtime state, resolve the definition when needed, and handle missing content where the lookup occurs:

Pickup.ItemId = Potion_Small

On Interact
-> Get Data Table Row(DT_Items, Pickup.ItemId)
   Row Found:
       validate gameplay rules
       add ItemId + Quantity to inventory
       use Out Row for icon, max stack, weight, and display text
   Row Not Found:
       Print String "Missing item definition: " + ItemId
       reject the pickup without mutating inventory

For data used repeatedly, resolve once at an event boundary and store the small values your runtime owner needs. Do not put table lookup in Tick or a UMG binding simply because it is available: repeated map lookup and struct copying hide work and make missing data harder to diagnose. Re-read deliberately when hot-reload/editor workflows actually require it.

The equivalent C++ pattern (original example code) is:

const FItemRow* FindItemRow(const UDataTable* ItemTable, FName ItemId)
{
    if (!ItemTable || ItemId.IsNone())
    {
        return nullptr;
    }

    return ItemTable->FindRow<FItemRow>(
        ItemId,
        TEXT("FindItemRow"),
        false); // This caller handles a missing row itself.
}

FindRow returns a pointer into table-owned row data in C++; Blueprint's node copies the row into its output. Do not keep a C++ row pointer across editor reimport or table mutation.

Lookalikes - which one do I want?

Tool What it answers Use it when
Get Data Table Row "Give me this typed row, and branch on success." Gameplay needs the row's fields now.
Does Data Table Row Exist "Does this key exist?" You only need a Boolean and do not need to copy the row. Avoid checking and then fetching when one Get can answer both.
Get Data Table Row Names "Which keys are in this table?" Building editor/debug lists or a small selection menu. Do not use display order as identity.
Break FItemRow "Split this struct value into fields." You already have a valid row. Breaking a struct does not perform lookup or validation.
Data Table Row Handle "Store a table plus one row name together." A property should let a designer choose both parts as one value. It still needs resolution and can still be stale.
Data Asset reference "Give me one authored asset object." Each definition should be its own rich asset instead of one same-shaped table row.
Map lookup "Find a runtime value by key." The values are mutable gameplay state, not read-only authored definitions.

Going deeper