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
Namekey called its row name. - Get Data Table Row asks one valid table for one row name. A match copies
that row into
Out Rowand runsRow Found; an absent key runsRow Not Found. - The output starts as a wildcard because different tables use different row
structs. Selecting
DT_Itemsmakes it anFItemRow; selectingDT_Enemiesmakes it anFEnemyRow. Row Not Foundis normal control flow for an optional or external ID. Do not readOut Rowthere: the node only promises a row onRow 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:
- Select a literal Data Table asset on the node. The asset carries its row struct, so the output changes to that type.
- Connect
Out Rowto 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¶
- Data Tables vs Data Assets - choose the authored-data container before wiring lookup.
- Data Table row names, row handles, and stable IDs - choose the durable key and migrate row renames.
- Structs, Enums, and Switch on Enum -
understand the row value copied through
Out Row. - Blueprint variables and references -
why a typed Data Table variable can still be
None. - Save Game: Create / Save / Load Game to Slot - persist stable IDs and runtime state rather than copied definition data.
- Engine source (requires engine access; we do not reproduce it):
UK2Node_GetDataTableRow::GetDataTableRowStructTypeandExpandNodeinEngine/Source/Editor/BlueprintGraph/Private/K2Node_GetDataTableRow.cpp;UDataTableFunctionLibrary::Generic_GetDataTableRowFromNameinEngine/Source/Runtime/Engine/Private/DataTableFunctionLibrary.cpp; andUDataTable::FindRow/GetRowMapinEngine/Source/Runtime/Engine/Classes/Engine/DataTable.h.