marmelab/react-admin · error · Error
Children of TranslatableInputs must have a source
Error message
Children of TranslatableInputs must have a source
What it means
TranslatableInputsTabContent builds a source context that suffixes each child input's source with the locale (e.g. 'description' becomes 'description.fr'). The getSource callback throws when a child reports an empty source, because there is nothing to namespace — every child of TranslatableInputs must declare a source.
Source
Thrown at packages/ra-ui-materialui/src/input/TranslatableInputsTabContent.tsx:45
const props = useThemeProps({
props: inProps,
name: PREFIX,
});
const { children, groupKey = '', locale, ...other } = props;
const { selectedLocale, getRecordForLocale } = useTranslatableContext();
const parentSourceContext = useSourceContext();
const record = useRecordContext(props);
// The SourceContext will be read by children of TranslatableInputs to compute their composed source and label
//
// <TranslatableInputs locales={['en', 'fr']} /> => SourceContext is "fr"
// <TextInput source="description" /> => final source for this input will be "description.fr"
// </TranslatableInputs>
const sourceContext = useMemo(
() => ({
getSource: (source: string) => {
if (!source) {
throw new Error(
'Children of TranslatableInputs must have a source'
);
}
return parentSourceContext.getSource(`${source}.${locale}`);
},
getLabel: (source: string) => {
return parentSourceContext.getLabel(source);
},
}),
[locale, parentSourceContext]
);
// As fields rely on the RecordContext to get their values and have no knowledge of the locale,
// we need to create a new record with the values for the current locale only
// Given the record { title: { en: 'title_en', fr: 'title_fr' } } and the locale 'fr',
// the record for the locale 'fr' will be { title: 'title_fr' }
const recordForLocale = useMemo(
() => getRecordForLocale(record, locale),View on GitHub (pinned to 051f511bb0)
Solutions
- Give every child input a source prop (e.g. <TextInput source="description" />).
- Move inputs that legitimately have no source outside of <TranslatableInputs>.
- For custom inputs, ensure they forward a non-empty source to the translatable context.
Example fix
// before
<TranslatableInputs locales={['en', 'fr']}>
<SelectInput choices={[{ id: 1, name: 'One' }]} />
</TranslatableInputs>
// after
<TranslatableInputs locales={['en', 'fr']}>
<SelectInput source="status" choices={[{ id: 1, name: 'One' }]} />
</TranslatableInputs> Defensive patterns
Strategy: validation
Validate before calling
React.Children.forEach(children, child => {
if (React.isValidElement(child) && !child.props.source) {
throw new Error('Children of TranslatableInputs must have a source');
}
}); Type guard
const hasSource = (c: React.ReactElement): c is React.ReactElement<{ source: string }> =>
typeof (c.props as { source?: string }).source === 'string' &&
(c.props as { source?: string }).source !== ''; Prevention
- Audit every child of TranslatableInputs for a source prop
- Keep non-translatable, source-less components outside TranslatableInputs
- Ensure custom inputs always forward a non-empty source
When it happens
Trigger: Placing an input without a source inside <TranslatableInputs> (e.g. a bare <SelectInput choices={...} />, a checkbox-only component, or a wrapper that strips source); rendering a component that calls getSource('') internally.
Common situations: Adding decorative/custom inputs inside TranslatableInputs; components that compute their source dynamically and yield an empty string; misusing TranslatableInputs around non-field components.
Related errors
- You can only provide one function child to AdminRouter
- <TranslatableFields> was called outside of a RecordContext a
- <TranslatableFields> was called outside of a ResourceContext
- <ReferenceArrayInput> only accepts a single child (like <Aut
- <InfiniteList> requires either a `render` prop or `children`
AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30).
Data as JSON: /api/errors/dd743182429f94c7.
Report an issue: GitHub.