avoid_banned_exports
Flags export directives for libraries you ban, optionally only inside the directories you name. Barrel-file hygiene: it keeps internal libraries out of a package’s public API.
A barrel file decides what a package promises. An export added there for convenience — to save one import in a test, say — silently makes everything in that library public, and removing it later is a breaking change for every consumer.
This is kept separate from avoid_banned_imports on purpose: depending on a library internally and re-exporting it to consumers are different decisions. A package is often free to use something it must not expose.
This rule is in no preset and reports nothing until you add banned:. Every example below shows the configuration that produces it.
many_lints: rules: avoid_banned_exports: banned: - deny_pattern: ['src/internal/.*'] in: ['lib/*.dart'] message: 'Internal libraries must not be part of the public API.'rules: avoid_banned_exports: banned: - deny_pattern: ['src/internal/.*'] in: ['lib/*.dart'] message: 'Internal libraries must not be part of the public API.'The URI is matched as written in the export directive. in: ['lib/*.dart'] is the useful default: a single * matches only top-level barrel files, so everything under lib/src/** stays free to export internally.
Examples
Section titled “Examples”Keep internal libraries out of the barrel
Section titled “Keep internal libraries out of the barrel”- deny_pattern: ['src/internal/.*'] in: ['lib/*.dart'] message: 'Internal libraries must not be part of the public API.'// Don't — in lib/my_package.dartexport 'src/internal/cache.dart'; // LINT: makes the cache public API// Do — in lib/my_package.dart: export only what consumers depend onexport 'src/api/client.dart';export 'src/api/models.dart';Stop a dependency leaking through your API
Section titled “Stop a dependency leaking through your API”Re-exporting a package makes its types part of your signature, so its next major version becomes your breaking change:
- deny: ['package:dio/dio.dart', 'package:http/http.dart'] in: ['lib/*.dart'] message: 'Wrap the HTTP client; do not re-export it.'// Don't — in lib/api_client.dartexport 'package:dio/dio.dart'; // LINT
// Do — expose your own types onlyexport 'src/api/api_client.dart';export 'src/api/api_failure.dart';Ban export entirely below the barrel
Section titled “Ban export entirely below the barrel”Omit deny in favour of a pattern that matches everything, scoped to the
directories where a re-export is never right:
- deny_pattern: ['.*'] in: ['lib/src/features/**'] message: 'Feature libraries import what they need; they re-export nothing.'// Don't — in lib/src/features/cart/cart.dartexport 'cart_controller.dart'; // LINT
// Doimport 'cart_controller.dart';
CartController build() => CartController();Keep a generated part out of the public surface
Section titled “Keep a generated part out of the public surface”- deny_pattern: ['.*\.g\.dart'] message: 'Generated code is an implementation detail.'// Don'texport 'models/user.g.dart'; // LINT
// Doexport 'models/user.dart';Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
banned |
list of entries | [] |
The entries to enforce. With none, the rule reports nothing |
Per entry:
| Key | Type | Required | Description |
|---|---|---|---|
deny |
string or list | one of deny / deny_pattern |
Export URIs banned by exact match |
deny_pattern |
string or list | one of deny / deny_pattern |
Regular expressions, anchored to the whole URI |
in |
list of globs | no | Paths, relative to the package root, where the entry applies. Omit to apply everywhere |
message |
string | no | A project-specific explanation appended to the diagnostic |
Known limitations
Section titled “Known limitations”The URI is matched as written. A relative export 'src/internal/cache.dart'; is matched as that relative path, not as a resolved package: URI — so an entry written one way does not catch the other. Write the spelling your codebase uses, or cover both.
show / hide are ignored. export 'src/internal/cache.dart' show Cache; is reported exactly like a bare export; the rule bans the library, not the symbols taken from it.
Chained exports are invisible. If a barrel exports a permitted library that itself exports a banned one, only the file with the banned line is reported.
A malformed entry is skipped silently. An invalid regular expression costs you that pattern and nothing else — a plugin cannot report problems against a YAML file.
Related rules
Section titled “Related rules”avoid_banned_annotations— Ban specific annotations, optionally scoped by directory.avoid_banned_imports— Ban imports of specific libraries, optionally scoped by directory.avoid_banned_names— Ban specific identifiers from being used as declaration names.avoid_banned_types— Ban specific types from being named, optionally scoped by directory.