Error: Cell values for field X are not loaded

Hi,
I’m trying to build an app based on the To-do list tutorial (https://airtable.com/developers/apps/guides/to-do-list-tutorial) for the Blocks SDK. Whenever I try to show a value with record.getCellValueAsString(‘someFieldId’) I get the following error:

Error: Cell values for field fldQYB8sxPz3dvhwH are not loaded
spawnErrorWithOriginOmittedFromStackTrace@https://localhost:9000/__runFrame/bundle.js:619:13
invariant@https://localhost:9000/__runFrame/bundle.js:661:11
getCellValueAsString@https://localhost:9000/__runFrame/bundle.js:6185:34
Booking@https://localhost:9000/__runFrame/bundle.js:162:91
renderWithHooks@https://localhost:9000/__runFrame/bundle.js:62042:27
mountIndeterminateComponent@https://localhost:9000/__runFrame/bundle.js:64576:13
beginWork$1@https://localhost:9000/__runFrame/bundle.js:65944:16
callCallback@https://localhost:9000/__runFrame/bundle.js:46118:14
x.wrap/e._wrapped@https://cdnjs.cloudflare.com/ajax/libs/rollbar.js/1.9.0/rollbar.nojson.min.js:1:13806
invokeGuardedCallbackDev@https://localhost:9000/__runFrame/bundle.js:46167:16
invokeGuardedCallback@https://localhost:9000/__runFrame/bundle.js:46222:31
beginWork$$1@https://localhost:9000/__runFrame/bundle.js:71562:28
performUnitOfWork@https://localhost:9000/__runFrame/bundle.js:70477:12
workLoopSync@https://localhost:9000/__runFrame/bundle.js:70453:22
performSyncWorkOnRoot@https://localhost:9000/__runFrame/bundle.js:70052:11
flushSyncCallbackQueueImpl/<@https://localhost:9000/__runFrame/bundle.js:57981:24
unstable_runWithPriority@https://localhost:9000/__runFrame/bundle.js:80507:12
runWithPriority$2@https://localhost:9000/__runFrame/bundle.js:57931:10
flushSyncCallbackQueueImpl@https://localhost:9000/__runFrame/bundle.js:57976:24
workLoop@https://localhost:9000/__runFrame/bundle.js:80451:42
flushWork@https://localhost:9000/__runFrame/bundle.js:80406:16
performWorkUntilDeadline@https://localhost:9000/__runFrame/bundle.js:80013:48
EventHandlerNonNull*[427]</<@https://localhost:9000/__runFrame/bundle.js:80040:3
[427]<@https://localhost:9000/__runFrame/bundle.js:80713:5
o@https://localhost:9000/__runFrame/bundle.js:1:265
o/<@https://localhost:9000/__runFrame/bundle.js:1:316
[429]<@https://localhost:9000/__runFrame/bundle.js:80746:20
o@https://localhost:9000/__runFrame/bundle.js:1:265
o/<@https://localhost:9000/__runFrame/bundle.js:1:316
[413]</<@https://localhost:9000/__runFrame/bundle.js:45802:24
[413]<@https://localhost:9000/__runFrame/bundle.js:73576:5
o@https://localhost:9000/__runFrame/bundle.js:1:265
o/<@https://localhost:9000/__runFrame/bundle.js:1:316
[415]<@https://localhost:9000/__runFrame/bundle.js:73908:20
o@https://localhost:9000/__runFrame/bundle.js:1:265
o/<@https://localhost:9000/__runFrame/bundle.js:1:316
[1]<@https://localhost:9000/__runFrame/bundle.js:3:23
o@https://localhost:9000/__runFrame/bundle.js:1:265
r@https://localhost:9000/__runFrame/bundle.js:1:432
@https://localhost:9000/__runFrame/bundle.js:1:460

I tried adding the id hardcoded or based on selecting the id into the global config (exactly as done with the doneField in the To-do tutorial) but not matter what I always get that error. Can someone help to understand what the error means?

Hey @Maximilian,

Welcome to the community! Sorry you’re running into this issue. Does this error reliably reproduce? From looking at the stack trace, I’m not immediately sure how the app got into this state. Would it be possible to share the code that triggered the error?

Hey @Billy_Littlefield, thx for your response. Here is some reduced version that causes the error on my side. It’s basically the to-do example I referred to but with an added “start” and “end” field. The problem is in the function Task() where I try to display the start value using

{record.getCellValueAsString(startField)}

import React, {useState} from 'react';
import {
    initializeBlock,
    useBase,
    useRecords,
    useGlobalConfig,
    expandRecord,
    TablePickerSynced,
    ViewPickerSynced,
    FieldPickerSynced,
    FormField,
    Input,
    Button,
    Box,
    Icon,
} from '@airtable/blocks/ui';
import {FieldType} from '@airtable/blocks/models';

function TodoApp() {
    const base = useBase();

    // Read the user's choice for which table and view to use from globalConfig.
    const globalConfig = useGlobalConfig();
    const tableId = globalConfig.get('selectedTableId');
    const viewId = globalConfig.get('selectedViewId');
    const doneFieldId = globalConfig.get('selectedDoneFieldId');
    const startFieldId = globalConfig.get('selectedStartFieldId');
    const endFieldId = globalConfig.get('selectedEndFieldId');

    const table = base.getTableByIdIfExists(tableId);
    const view = table ? table.getViewByIdIfExists(viewId) : null;
    const doneField = table ? table.getFieldByIdIfExists(doneFieldId) : null;
    const startField = table ? table.getFieldByIdIfExists(startFieldId) : null;
    const endField = table ? table.getFieldByIdIfExists(endFieldId) : null;

    // Don't need to fetch records if doneField doesn't exist (the field or it's parent table may
    // have been deleted, or may not have been selected yet.)
    const records = useRecords(doneField ? view : null, {
        fields: doneField ? [table.primaryField, doneField] : [],
    });

    const tasks = records
        ? records.map(record => {
              return <Task key={record.id} record={record} table={table} doneField={doneField} startField={startField} endField={endField} />;
          })
        : null;

    return (
        <div>
            <Box padding={3} borderBottom="thick">
                <FormField label="Table">
                    <TablePickerSynced globalConfigKey="selectedTableId" />
                </FormField>
                <FormField label="View">
                    <ViewPickerSynced table={table} globalConfigKey="selectedViewId" />
                </FormField>
                <FormField label="Field" marginBottom={0}>
                    <FieldPickerSynced
                        table={table}
                        globalConfigKey="selectedDoneFieldId"
                        placeholder="Pick a 'done' field..."
                        allowedTypes={[FieldType.CHECKBOX]}
                    />
                </FormField>
                <FormField label="Start Field" marginBottom={0}>
                    <FieldPickerSynced
                        table={table}
                        globalConfigKey="selectedStartFieldId"
                        placeholder="Pick a 'start' field..."
                        allowedTypes={[FieldType.SINGLE_LINE_TEXT]}
                    />
                </FormField>
                <FormField label="End Field" marginBottom={0}>
                    <FieldPickerSynced
                        table={table}
                        globalConfigKey="selectedEndFieldId"
                        placeholder="Pick a 'end' field..."
                        allowedTypes={[FieldType.DATE_TIME]}
                    />
                </FormField>
            </Box>
            {tasks}
            {table && doneField && <AddTaskForm table={table} />}
        </div>
    );
}

function Task({record, table, doneField, startField}) {
    return (
        <Box
            fontSize={4}
            paddingX={3}
            paddingY={2}
            marginRight={-2}
            borderBottom="default"
            display="flex"
            alignItems="center"
        >
            <TaskDoneCheckbox table={table} record={record} doneField={doneField} />
            <a
                style={{cursor: 'pointer', flex: 'auto', padding: 8}}
                onClick={() => {
                    expandRecord(record);
                }}
            >
                {record.name || 'Unnamed record'}
            </a>

            <p>{record.getCellValueAsString(startField)}</p> // THIS IS CAUSING THE ERROR

            <TaskDeleteButton table={table} record={record} />
        </Box>
    );
}

Thx for your help :slight_smile:

Hey @Maximilian,

Thanks for sharing the code! I think I see what’s going on here. On L38-40, you’re loading the record data with this code:

const records = useRecords(doneField ? view : null, {
    fields: doneField ? [table.primaryField, doneField] : [],
});

The second argument to useRecords is currently saying “only load data for the ‘primary field’ and ‘done field’”. So, when you try to lookup data for the ‘start field’ (which wasn’t loaded) in the Task component, we see this error.

The solution is to either just remove that second argument to useRecords entirely, or (if you’d like to continue selectively loading data), ensure all fields you’ll be accessing are included in the fields array.

For added context, the primary purpose of that second argument is to limit the amount of data sent over to the block for performance reasons (e.g. in a base with 10000s of records and 100s of fields, don’t send over all the data if we don’t need it).

Cheers,
Billy

1 Like

This topic was solved and automatically closed 3 days after the last reply. New replies are no longer allowed.