> For the complete documentation index, see [llms.txt](https://codemash.gitbook.io/codemash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codemash.gitbook.io/codemash/cloud/database/schema/field-types/file.md).

# File

Uploaded files linked to a record: an array of file ids, with the allowed storages, file kind, size and count.

A **File** field links uploaded files to the record. The record stores only the **file ids**; the file itself lives in the Files module. The schema says which storages are allowed, what kind of file, how big and how many.

**Builder:** Form fields panel → **File** · widget `file` · data type `file.schema.v1`

## Data schema

```json
{
  "photos": {
    "type": "array",
    "items": { "type": "string", "format": "uuid" },
    "minItems": 0,
    "maxItems": 3,
    "meta": {
      "storages": ["fil_6Q0lfz2fQmU4yY0pG3f9bA"],
      "allowedFileType": "images",
      "maxSize": 5
    }
  }
}
```

| Keyword                 | Required | What it does                                                                                       | Example     |
| ----------------------- | -------- | -------------------------------------------------------------------------------------------------- | ----------- |
| `type`                  | yes      | Always `"array"` — even a single file is a list of one.                                            | `"array"`   |
| `items`                 | yes      | Always `{ "type": "string", "format": "uuid" }` — this shape is what makes the field a File field. |             |
| `minItems` / `maxItems` | no       | The fewest / most files. `maxItems: 1` = one file.                                                 | `0` / `3`   |
| `meta.storages`         | no       | The files-integration ids a file may live in. Left out = the environment's default storage.        | `["fil_…"]` |
| `meta.allowedFileType`  | no       | The upload kind the picker offers (`images`, …).                                                   | `"images"`  |
| `meta.maxSize`          | no       | The largest file, in **MB per file**.                                                              | `5`         |

### What the server refuses

Every write — insert, update, replace; from Cloud, the API, an SDK, the CLI or an AI agent — is checked against the published schema. A broken value is answered with one error per field: the code, and `Field '<name>' is invalid: <reason>`. Nothing is written.

| Case                                               | Code                     | The reason it gives                                          |
| -------------------------------------------------- | ------------------------ | ------------------------------------------------------------ |
| a required field is missing or `null`              | `CM-ERRORS-DATABASE-030` | `a value is required`                                        |
| not an array                                       | `CM-ERRORS-DATABASE-039` | `must be an array of file ids`                               |
| an entry that is not a file id                     | `CM-ERRORS-DATABASE-042` | `'abc' is not a file id (a UUID or an nbfl_… id)`            |
| an id no allowed storage holds (or a deleted file) | `CM-ERRORS-DATABASE-054` | `'…' is not a file in the storage(s) this field allows`      |
| the same id twice                                  | `CM-ERRORS-DATABASE-046` | `entries must be unique — repeated: '…'`                     |
| fewer than `minItems` / more than `maxItems`       | `CM-ERRORS-DATABASE-040` | `must have at least 1 files` / `must have at most 3 files`   |
| the storage cannot be opened in this environment   | `CM-ERRORS-DATABASE-055` | `its target 'files:…' cannot be read in this environment: …` |

A keyword that is not in the table above is refused when the schema is **saved**, not when a record is written: `CM-ERRORS-SCHEMA-010` — `Data schema violates meta-schema: Property 'sort' has not been defined and the schema does not allow additional properties. Path 'properties.photos.sort' (field 'properties.photos' checked as file.schema.v1).`

## UI schema

The cell uses the `file` widget (**Pick a file**). `file.path` is the folder new uploads go into — a form hint; which storages are allowed is the data rule `meta.storages`.

```json
{
  "colSpan": 3,
  "element": {
    "fieldId": "photos",
    "meta": { "widget": "file", "label": "Photos", "file": { "path": "/products/photos" } }
  }
}
```

| Option      | What it does                                                                     |
| ----------- | -------------------------------------------------------------------------------- |
| `file.path` | The folder inside the project's files storage the picker uploads new files into. |

Every cell also takes the common layout options: `label`, `placeholder`, `help` (the text under the input), `required`, `readonly` and `hidden`. Keys outside this list — `watermark`, `hint`, `permissions` — are refused when the schema is saved (`CM-ERRORS-SCHEMA-012`), see [Schema authoring guide](/codemash/cloud/database/schema.md#one-contract-no-second-dialect).

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-778f1601331ac885bd19ca53c1a48640c906a286%2Ffield-types-lists-1.png?alt=media" alt="The Lists &#x26; files tab of the all-types record form with file cells (File plain, File type, File min items, File max items, File items) each showing Pick a file and a search icon"><figcaption><p>File cells on the Lists &#x26; files tab.</p></figcaption></figure>

## Records

A record the schema accepts:

```json
{ "photos": ["3f1c9b2e-7d4a-4c1e-9b0a-2f6e8d1a5c77"] }
```

A record it refuses:

```json
{ "photos": ["not-a-file-id"] }
```

The answer: `CM-ERRORS-DATABASE-042` — `Field 'photos' is invalid: 'not-a-file-id' is not a file id (a UUID or an nbfl_… id)`. In Cloud the same sentence is shown under the field before the form is sent; the server repeats the check on every API write.

## Good to know

* The server checks on every write that each id **exists** in an allowed storage of the request's environment — a file uploaded to another storage is refused with `CM-ERRORS-DATABASE-054`.
* `maxSize` and `allowedFileType` are checked at upload time by the picker and the Files API, not against the id on the record.
* Read a file by its id with the Files API (`getFile`); `expandReferences` on a find answers `{ id, display }` for file fields too, see [References](/codemash/cloud/database/schema/references.md).

## Do it from code

```ts
await norbix.api.database.insertOne({
  collectionName: 'products',
  document: JSON.stringify({ photos: ['3f1c9b2e-7d4a-4c1e-9b0a-2f6e8d1a5c77'] }),
});
```

```sh
norbix api database one insert --collectionName products --document '{"photos":["3f1c9b2e-7d4a-4c1e-9b0a-2f6e8d1a5c77"]}'
```

The client setup is on the [Database page](/codemash/cloud/database.md#use-it-from-code). API: [Insert One](/codemash/api-reference/database/collections/insert-one.md) · [Save Database Schema](/codemash/api-reference/database/schemas/save-database-schema.md)

## Related

[Files module](/codemash/cloud/files.md) · [References](/codemash/cloud/database/schema/references.md) · [Array](/codemash/cloud/database/schema/field-types/array.md) · [Field type reference](/codemash/cloud/database/schema/field-types.md) · [Schema authoring guide](/codemash/cloud/database/schema.md) · [Create a schema](/codemash/cloud/database/collections/create-schema.md)
