> ## Documentation Index
> Fetch the complete documentation index at: https://flux-docs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Supported Types

> Every value Flux can serialize, and everything it cannot.

Flux automatically serializes the following types.

## Supported

Hover any icon for what it means in that column.

| Type         | Dynamic                                                                                                                               | Schema constructor                              | Lossless                                                                                                                                                                                                   |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `nil`        | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.Optional(...)`                               | <Tooltip tip="Round-trips exactly: the value received equals the value sent."><Icon icon="check" color="#16a34a" /></Tooltip>                                                                              |
| `boolean`    | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.Bool()`                                      | <Tooltip tip="Round-trips exactly: the value received equals the value sent."><Icon icon="check" color="#16a34a" /></Tooltip>                                                                              |
| `number`     | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.UInt8/16/32`, `T.Int8/16/32`, `T.Float32/64` | <Tooltip tip="Round-trips exactly: the value received equals the value sent."><Icon icon="check" color="#16a34a" /></Tooltip>                                                                              |
| `string`     | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.String(maxLen?)`                             | <Tooltip tip="Round-trips exactly: the value received equals the value sent."><Icon icon="check" color="#16a34a" /></Tooltip>                                                                              |
| `buffer`     | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | not available                                   | <Tooltip tip="Round-trips exactly: the value received equals the value sent."><Icon icon="check" color="#16a34a" /></Tooltip>                                                                              |
| `table`      | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.Array`, `T.Struct`                           | <Tooltip tip="Caveats apply: sparse tables are reshaped, metatables and functions are dropped, and circular references overflow the stack."><Icon icon="triangle-exclamation" color="#d97706" /></Tooltip> |
| `Instance`   | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.Instance()`                                  | <Tooltip tip="Caveats apply: arrives as nil if the receiver cannot see the instance."><Icon icon="triangle-exclamation" color="#d97706" /></Tooltip>                                                       |
| `Vector2`    | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.Vector2()`                                   | <Tooltip tip="Caveats apply: components are sent as 32-bit floats, so full Luau number precision is not preserved."><Icon icon="triangle-exclamation" color="#d97706" /></Tooltip> `f32`                   |
| `Vector3`    | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.Vector3()`                                   | <Tooltip tip="Caveats apply: components are sent as 32-bit floats, so full Luau number precision is not preserved."><Icon icon="triangle-exclamation" color="#d97706" /></Tooltip> `f32`                   |
| `CFrame`     | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.CFrame()`                                    | <Tooltip tip="Lossy: rotation is sent as axis-angle and rebuilt, so it will not match the original matrix bit-for-bit."><Icon icon="xmark" color="#dc2626" /></Tooltip> axis-angle                         |
| `Color3`     | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.Color3()`                                    | <Tooltip tip="Lossy: each channel is quantised to 8 bits with a downward floor bias."><Icon icon="xmark" color="#dc2626" /></Tooltip> 8-bit                                                                |
| `BrickColor` | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | not available                                   | <Tooltip tip="Round-trips exactly: the value received equals the value sent."><Icon icon="check" color="#16a34a" /></Tooltip>                                                                              |
| `Region3`    | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | not available                                   | <Tooltip tip="Lossy: rebuilt axis-aligned from position and size, discarding any rotation."><Icon icon="xmark" color="#dc2626" /></Tooltip> loses rotation                                                 |
| `EnumItem`   | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | `T.Enum(enum)`                                  | <Tooltip tip="Round-trips exactly: the value received equals the value sent."><Icon icon="check" color="#16a34a" /></Tooltip>                                                                              |
| `UDim`       | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | not available                                   | <Tooltip tip="Caveats apply: the scale is sent as a 32-bit float, so full Luau number precision is not preserved."><Icon icon="triangle-exclamation" color="#d97706" /></Tooltip> `f32` scale              |
| `UDim2`      | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | not available                                   | <Tooltip tip="Caveats apply: the scale is sent as a 32-bit float, so full Luau number precision is not preserved."><Icon icon="triangle-exclamation" color="#d97706" /></Tooltip> `f32` scale              |
| `TweenInfo`  | <Tooltip tip="Encoded automatically by the dynamic encoder, with no schema required."><Icon icon="check" color="#16a34a" /></Tooltip> | not available                                   | <Tooltip tip="Round-trips exactly: the value received equals the value sent."><Icon icon="check" color="#16a34a" /></Tooltip>                                                                              |

<Note>
  Six supported datatypes have no schema constructor: `buffer`, `BrickColor`, `Region3`, `UDim`,
  `UDim2` and `TweenInfo`. Under a schema, use `T.Any()` or write a
  [custom type](/api/types#custom-types).
</Note>

## Not supported

Sending any of these logs `warn("Unsupported type: ...")` on the sender, and the receiver gets
`nil`.

| Type                              | Send instead                                        |
| --------------------------------- | --------------------------------------------------- |
| `function`                        | An id or name the receiver maps to a local function |
| `thread`                          | nothing equivalent                                  |
| `Vector2int16`, `Vector3int16`    | Components as `T.Int16()`                           |
| `NumberRange`                     | Two numbers                                         |
| `NumberSequence`, `ColorSequence` | An array of keypoint structs                        |
| `Ray`                             | Origin and direction as two `Vector3`               |
| `Rect`                            | Two `Vector2`                                       |
| `Axes`, `Faces`                   | A bitfield in a `T.UInt8()`                         |
| `PhysicalProperties`              | Its six numbers                                     |
| `Font`                            | Family string and weight enum                       |
| `DateTime`                        | `dateTime.UnixTimestamp` as `T.Float64()`           |
| `RBXScriptSignal` / `Connection`  | nothing equivalent                                  |
| Metatables, `newproxy` userdata   | nothing equivalent                                  |

<Warning>
  This failure is silent on the receiving side. The argument count still matches, so your callback
  runs with a `nil` in that position and the only clue is one warning in the sender's output.
  Check this table before sending an unusual datatype.
</Warning>

## Tables

<AccordionGroup>
  <Accordion title="Arrays, dense 1..n" icon="list-ol">
    Written as `TYPE_ARRAY` plus a varint count. Round-trips exactly.

    ```luau theme={null}
    MyEvent:Fire({ 10, 20, 30 })  --> { 10, 20, 30 }
    ```
  </Accordion>

  <Accordion title="Dictionaries" icon="table">
    Written as `TYPE_TABLE` with alternating keys and values. Keys are themselves dynamically
    encoded, so any serializable type works as a key.

    ```luau theme={null}
    MyEvent:Fire({ Health = 100, Team = "Red" })
    ```
  </Accordion>

  <Accordion title="Mixed tables" icon="shuffle">
    Fail the array test and take the dictionary path, which preserves both parts.

    ```luau theme={null}
    MyEvent:Fire({ 1, 2, Name = "x" })  --> { 1, 2, Name = "x" }
    ```
  </Accordion>

  <Accordion title="Sparse tables, reshaped" icon="triangle-exclamation">
    A table with gaps also takes the dictionary path, so it arrives as a dictionary with numeric
    keys rather than an array. `#result` is unreliable and `ipairs` stops at the first gap.

    ```luau theme={null}
    MyEvent:Fire({ [1] = "a", [3] = "c" })
    -- arrives as { [1] = "a", [3] = "c" }, and #result is 1
    ```
  </Accordion>

  <Accordion title="Circular references, stack overflow" icon="circle-exclamation">
    Recursion has no visited-set and no depth limit.

    ```luau theme={null}
    local t = {}
    t.self = t
    MyEvent:Fire(t)  -- STACK OVERFLOW
    ```

    Break cycles before sending, or send an id and let the receiver rebuild.
  </Accordion>

  <Accordion title="Metatables and non-data fields" icon="ban">
    Metatables are never transmitted, so a received table is always a plain table.
    Function-valued fields become `nil` with a warning, which means an OOP instance arrives as its
    data fields only, without its methods.
  </Accordion>
</AccordionGroup>

## Numbers

The dynamic encoder narrows integers automatically.

| Value                | Encoded as | Payload bytes |
| -------------------- | ---------- | ------------- |
| `0` to `255`         | `u8`       | 1             |
| `256` to `65,535`    | `u16`      | 2             |
| `65,536` to `2^32-1` | `u32`      | 4             |
| `-1` to `-32,768`    | `i16`      | 2             |
| `-32,769` to `-2^31` | `i32`      | 4             |
| any non-integer      | `f64`      | 8             |
| beyond the above     | `f64`      | 8             |

<Note>
  There is no automatic `f32` narrowing and no `i8` selection. Every non-integer costs 8 bytes,
  and small negatives cost 2 where the same magnitude positive costs 1. Declare `T.Float32()` or
  `T.Int8()` in a schema to get those widths.
</Note>

<Warning>
  `nan` and `inf` are non-integers and go through `f64`, which transmits them faithfully. They
  will then propagate into the receiver's arithmetic, so validate before sending.
</Warning>

## Instances

<ResponseField name="Encoding" type="varint index, 1 to 3 bytes">
  Instances ride in a side array passed alongside the buffer, and only an index is serialized.
  Cheap regardless of tree depth, and deduplicated within a batch.
</ResponseField>

<ResponseField name="Failure mode" type="nil">
  If the receiver cannot see the instance, whether server-only, not replicated, or destroyed
  before the flush, the index resolves to `nil`. No error is raised.
</ResponseField>

```luau theme={null}
Highlight:Connect(function(part)
	if not part then return end
	-- safe
end)
```

## Multiple return values

`OnInvoke` may return any number of values, and all of them survive.

```luau theme={null}
-- Server
Shop.OnInvoke = function(player, itemId)
	return true, itemId, priceOf(itemId), os.time()
end

-- Client
local ok, item, price, at = Shop:Invoke("sword")
```

<Note>
  Invoke traffic always uses the dynamic encoder regardless of any schema, which is precisely why
  a variable return count works without you declaring anything. See
  [Invocations](/guides/invocations#invocations-ignore-schemas).
</Note>

## Next steps

<CardGroup cols={2}>
  <Card title="Known limits" icon="triangle-exclamation" href="/reference/limits">
    Every rough edge in one place.
  </Card>

  <Card title="Serialization" icon="binary" href="/concepts/serialization">
    Why the encoder makes these choices.
  </Card>
</CardGroup>
