facebook/flow · error
Records cannot have getters
Error message
Records cannot have getters
What it means
In Flow record declarations, the typing pass panics on MethodKind::Get: records have no accessor semantics, so a getter in a record body crashes the statement typer rather than producing a diagnostic. Like the constructor case, this is an intentional hard boundary — records only model data plus plain methods.
Source
Thrown at rust_port/crates/flow_typing_statement/src/statement.rs:18860
}),
),
value: (func_loc_c, typed_func),
kind: kind_c,
static_: static_c,
override_: false,
ts_accessibility: None,
decorators: vec![].into(),
comments: method_comments_c,
},
))
};
match kind {
ast::class::MethodKind::Constructor => {
panic!("Records cannot have constructors")
}
ast::class::MethodKind::Get => {
panic!("Records cannot have getters")
}
ast::class::MethodKind::Set => {
panic!("Records cannot have setters")
}
ast::class::MethodKind::Method => {
check_duplicate_name(
&mut public_seen_names,
method_id_loc.dupe(),
&Name::new(name.dupe()),
static_,
false,
ClassMemberKind::ClassMemberMethod,
);
class_sig::add_method(
static_,
false,
false,
Name::new(name),View on GitHub (pinned to 5c86586199)
Solutions
- Remove the getter from the record body.
- Replace derived values with a plain function taking the record: function getName(c: Config): string.
- Keep accessors by using a class instead of a record.
- Add a lint rule that rejects accessor members inside record bodies.
Example fix
// before
record Config {
name_: string;
get name(): string { return this.name_; }
}
// after: compute via a function
record Config { name: string; }
function getName(c: Config): string { return c.name; } Defensive patterns
Strategy: validation
Validate before calling
// lint before typechecking: records must not contain getters
function recordHasAccessor(node) {
return node.body.some(
(el) => el.type === 'Method' && (el.kind === 'get' || el.kind === 'set')
);
}
if (recordHasAccessor(recordNode)) reportError(recordNode, 'records cannot have accessors'); Type guard
function recordMemberAllowed(el) {
if (el.type === 'Property') return true;
if (el.type !== 'Method') return false;
return el.kind === 'method' && el.key.type === 'Identifier';
} Prevention
- Teach refactoring tools that record is data-only: derived values become plain functions.
- Add accessor-in-record to the lint config together with the constructor rule.
- Review codemod output for accessor members before committing conversions.
- Prefer classes when accessors carry real behavior.
When it happens
Trigger: Typechecking a record whose body contains a getter — record Config { get name(): string { ... } } — where the parser accepted the accessor and typing reaches the member lowering.
Common situations: Class-to-record conversions that keep accessors; developers assuming record getters behave like class getters; codemods and code generators emitting accessors into record bodies.
Related errors
- Records cannot have constructors
- Records cannot have setters
- Records cannot have private methods
- Records can only have identifier method keys
- Unexpected function parameter ${param.type}
AI-assisted analysis of facebook/flow@5c86586199 (2026-08-20).
Data as JSON: /api/errors/8fac7f5d09deafdb.
Report an issue: GitHub.