Skip to content

avoid_default_tostring

v0.8.0WarningConfigurableCode Quality

This rule flags string interpolation of a value whose class does not override toString.

Object.toString returns Instance of 'Foo'. That is the one piece of information the reader of a log already has — the type — and none of the information they need.

The cost lands exactly where it hurts most: an error message written to diagnose a failure, or a log line captured from production, that turns out to say nothing. By the time anyone notices, the incident is over and the data is gone.

class User {
const User(this.id, this.email);
final String id;
final String email;
}
void logFailure(User user) {
// Logs: "failed for Instance of 'User'"
logger.severe('failed for $user');
}
class User {
const User(this.id, this.email);
final String id;
final String email;
@override
String toString() => 'User(id: $id, email: $email)';
}
void logFailure(User user) {
logger.severe('failed for $user');
}

Or interpolate the fields you actually need:

logger.severe('failed for ${user.id}');

Only classes declared in the analysed code are reported. A type from the SDK or a third-party package without a toString is not something the user can fix, so it is skipped.

The check walks the full supertype chain, so a class inheriting toString from a base class is not flagged. Enums, records, and core types render usefully by default and are never reported.

This rule is in the opinionated preset, so it is on with preset: opinionated, or by name:

many_lints.yaml
rules:
avoid_default_tostring: true

To turn it off again:

many_lints.yaml
rules:
avoid_default_tostring: false

To keep the rule on but skip certain paths, use per-rule exclude.

analysis_options.yaml
many_lints:
rules:
avoid_default_tostring:
report_enums: true
Option Type Default Description
report_enums bool false Also report interpolated enums without a toString override. Off by default because Status.active already reads well