flutter-dio-engineering
Skill8 starsChanged 48 days agoMITView on GitHub
Design, implement, review, debug, secure, test, refactor, and optimize production Flutter/Dart networking built with Dio 5.x. Use this skill whenever a Flutter task involves Dio clients, REST/HTTP APIs, BaseOptions/Options, interceptors, bearer authentication, token refresh, retries, cancellation, uploads/downloads, streaming, transformers, cookies, caching, adapters, TLS/certificates, proxies, HTTP/2, Flutter Web/CORS, networking errors, DTOs, repositories, observability, performance, or migration from older Dio APIs—even if the user only asks to add or fix one API call.
In this repository70 other files it gives its agents.
- camerawesome-flutterSkill
- dart-args-production-cliSkill
- dart-flutter-equatable-engineeringSkill
- dart-flutter-ffi-systems-engineeringSkill
- dart-metaSkill
- document-camera-frameSkill
- document-scan-flutterSkill
- figma-to-flutter-expertSkill
- flutter-animations-production-engineeringSkill
- flutter-app-hardening-reverse-engineeringSkill
- flutter-app-icon-engineeringSkill
- flutter-application-security-engineeringSkill
- flutter-app-links-deep-link-engineeringSkill
- flutter-cachingSkill
- flutter-concurrency-memory-performanceSkill
- flutter-confetti-engineeringSkill
- flutter-dart-package-engineeringSkill
- flutter-design-system-from-design-mdSkill
- flutter-dio-cache-interceptor-engineeringSkill
- flutter-doc-scannerSkill
- flutter-drift-persistence-engineeringSkill
- flutter-expert-tipsSkill
- flutter-firebase-analyticsSkill
- flutter-firebase-core-engineeringSkill
- flutter-firebase-messagingSkill
- flutter-get-it-injectable-dependency-injectionSkill
- flutter-go-router-engineeringSkill
- flutter-hive-persistence-engineeringSkill
- flutter-image-performanceSkill
- flutter-image-picker-production-engineeringSkill
- flutter-lints-static-analysis-engineeringSkill
- flutter-local-notifications-production-engineeringSkill
- flutter-memory-leak-engineeringSkill
- flutter-mobile-developmentSkill
- flutter-motion-engineeringSkill
- flutter-multi-environmentSkill
- flutter-native-splash-engineeringSkill
- flutter-package-plugin-selectionSkill
- flutter-path-provider-production-storageSkill
- flutter-performance-jank-optimizationSkill
- flutter-permission-handler-engineeringSkill
- flutter-pinputSkill
- flutter-production-build-releaseSkill
- flutter-production-engineeringSkill
- flutter-production-loggingSkill
- flutter-pro-image-editor-engineeringSkill
- flutter-secure-storage-security-engineeringSkill
- flutter-sentry-engineeringSkill
- flutter-share-plus-engineeringSkill
- flutter-skeletonizer-engineeringSkill
- flutter-squadron-concurrency-engineeringSkill
- flutter-supabase-engineeringSkill
- flutter-svg-engineeringSkill
- flutter-ui-performance-engineeringSkill
- flutter-url-launcher-engineeringSkill
- flutter-video-player-production-engineeringSkill
- flutter-webview-production-engineeringSkill
- freezed-production-engineeringSkill
- html-to-flutterSkill
- hydrated-blocSkill
- The first 60 shown.
The file
Show its rules and text
We split this skill into the rules it gives an agent
50 rules. About 0 are common, 33 are distinctive, and 17 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈33
Distinctive · estimate
This author's own choices. Worth a look.
17
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Treat Dio as the transport layer, not the application architecture.
- Distinctive: line 22
Keep Dio behind typed API/data abstractions.
- Distinctive: line 24
Keep business rules and navigation out of interceptors.
- Very specific: line 25
Keep dynamic credentials out of long-lived static BaseOptions.headers.
- Distinctive: line 29
Treat intentional cancellation separately from connectivity failure.
- Distinctive: line 30
Use streaming/file-oriented APIs for large transfers instead of buffering without need.
- Distinctive: line 31
Never log bearer tokens, refresh tokens, cookies, passwords, confidential credentials, payment data, or sensitive bodies.
- Distinctive: line 32
Never disable TLS verification in production.
- Very specific: line 33
Do not attempt to solve Web CORS with client-side Access-Control-Allow-* request headers.
- Distinctive: line 34
Test networking deterministically through injected clients/adapters.
- Distinctive: line 39
Before editing a repository:
- Very specific: line 44
check for deprecated names such as DioError, DioErrorType, legacy adapters, or old transformer examples.
- Distinctive: line 51
Do not present architecture inference as a Dio API guarantee.
- Distinctive: line 53
Read only the references needed for the task:
- Distinctive: line 93
every interceptor and whether it is queued.
- Distinctive: line 102
Do not add a second competing mechanism until you understand the existing one.
- Distinctive: line 144
Avoid giant catch-all API services when feature/service-scoped clients reduce coupling.
- Distinctive: line 148
Create a distinct client when a material boundary differs, such as:
- Very specific: line 155
Do not create a new client merely because one endpoint is different.
- Very specific: line 157
Use BaseOptions only for real client-wide defaults such as base URL, common Accept, coherent timeout defaults, shared redirect policy, or …
- Very specific: line 159
Use request Options for endpoint-specific:
- Very specific: line 168
Use extra for local transport metadata consumed by interceptors/transformers.
- Distinctive: line 170
Do not globally force JSON content type if the client also sends multipart or other body types.
- Distinctive: line 180
keep refresh requests out of the bearer-refresh recursion path.
- Very specific: line 185
keep login navigation outside interceptors.
- Very specific: line 186
Prefer a shared refresh Future when only refresh work needs serialization.
- Distinctive: line 190
Use interceptors for transport-wide concerns such as:
- Distinctive: line 234
Do not copy one arbitrary tuple to every endpoint.
- Distinctive: line 236
Before any automatic retry, answer:
- Very specific: line 250
Treat access-token 401 as auth-refresh flow, not generic retry.
- Very specific: line 252
Use CancelToken when work can become obsolete:
- Distinctive: line 253
search superseded by a new query.
- Distinctive: line 258
Do not share one token across unrelated requests.
- Distinctive: line 261
Keep raw JSON at the data boundary.
- Very specific: line 263
Before custom JSON isolation/transformation, inspect current FusedTransformer behavior and measure.
- Very specific: line 265
Use FormData/MultipartFile or streams appropriate to the platform.
- Distinctive: line 268
avoid loading the entire file into memory when path/stream APIs exist.
- Distinctive: line 270
use server resumable/idempotent protocols when retry is required.
- Very specific: line 277
do not append a full 200 OK body to a partial file.
- Distinctive: line 282
Treat Flutter Web as browser networking:
- Very specific: line 286
use BrowserHttpClientAdapter(withCredentials: true) only when the server's credentialed CORS policy supports it.
- Distinctive: line 298
Use request signing only when the key architecture actually supports the intended trust model.
- Distinctive: line 313
avoid unnecessary queued interceptor serialization.
- Distinctive: line 321
Do not replace adapters, transformers, or protocols because they appear more advanced.
- Very specific: line 331
Run the repository's normal formatter/analyzer/test commands after changes.
- Distinctive: line 335
document the backend contract.
- Distinctive: line 345
verify refresh behavior if authenticated.
- Very specific: line 350
run format/analyze/tests.
- Distinctive: line 352
When reviewing a networking implementation, report:
- Distinctive: line 409
If a critical condition cannot be evidenced, report the layer as not approved for production and identify the missing verification.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Flutter Dio Engineering
Operating stance
Treat Dio as the transport layer, not the application architecture. Preserve this priority order:
- correctness
- security
- reliability
- maintainability
- testability
- performance
- scalability
- developer experience
Apply these invariants:
- Reuse a coherently configured
Dioinstance; do not constructDio()per request. - Interpret reuse by networking-policy boundary, not as one mutable process-global client for unrelated origins or security policies.
- Keep Dio behind typed API/data abstractions; widgets and state-management code should not depend on raw Dio internals.
- Map
DioExceptioninto application/repository failures at the data boundary. - Keep business rules and navigation out of interceptors.
- Keep dynamic credentials out of long-lived static
BaseOptions.headers. - Filter endpoint-specific policy through request
Options/extrainstead of mutating global client state. - Prevent token-refresh recursion and concurrent refresh storms.
- Retry only when method/backend semantics make repetition safe; bound attempts and total cost.
- Treat intentional cancellation separately from connectivity failure.
- Use streaming/file-oriented APIs for large transfers instead of buffering without need.
- Never log bearer tokens, refresh tokens, cookies, passwords, confidential credentials, payment data, or sensitive bodies.
- Never disable TLS verification in production.
- Do not attempt to solve Web CORS with client-side
Access-Control-Allow-*request headers. - Test networking deterministically through injected clients/adapters; ordinary unit tests must not require live production services.
- Profile before replacing current Dio defaults such as its transformer or adapter.
Version and evidence gate
The supplied guide targets current Dio 5.x behavior and specifically discusses Dio 5.11-era APIs such as transformTimeout, FusedTransformer, current multipart behavior, and concurrency fixes.
Before editing a repository:
- inspect
pubspec.yamlandpubspec.lock; - identify locked
dio,dio_http2_adapter,dio_cookie_manager, and related versions; - inspect Flutter/Dart constraints and target platforms;
- check for deprecated names such as
DioError,DioErrorType, legacy adapters, or old transformer examples; - preserve source-supported distinctions:
- Dio behavior: documented/source-backed contract;
- Official Dio recommendation: package recommendation;
- Architecture recommendation: design inference;
- General HTTP/security practice: protocol/security guidance rather than a Dio-specific rule.
Do not present architecture inference as a Dio API guarantee.
Reference routing
Read only the references needed for the task:
| Task | Read |
Client lifecycle, request pipeline, BaseOptions, Options, RequestOptions, typed API clients, repository boundaries | references/01-architecture-client-options.md |
Authentication, interceptors, QueuedInterceptor, shared refresh Future, DioException, timeouts, cancellation, retry/idempotency, concurrency | references/02-auth-interceptors-reliability.md |
DTO mapping, multipart, uploads/downloads, streaming, FusedTransformer, logging/security, Web/CORS, cookies, caching, adapters, proxy, HTTP/2, performance | references/03-data-transfers-platform-performance.md |
| Bloc/Cubit integration, fake adapters, tests, observability, common anti-patterns | references/04-testing-observability-antipatterns.md |
| New-feature workflow, existing-code audit, debugging, refactoring, review/performance/security/production checklists, quick reference | references/05-workflows-debugging-checklists.md |
| For a broad networking audit, read all five references after completing the repository inventory below. |
Repository inventory
Inspect before changing code.
Client topology
Find every:
Dio(/Dio()construction;- clone/factory/client wrapper;
BaseOptionsmutation;httpClientAdaptercustomization;close()call. For each client record:- owner and lifetime;
- base origin;
- authentication policy;
- interceptor order;
- timeout policy;
- adapter/TLS/proxy policy;
- target platforms;
- who is allowed to close it.
Request/data boundaries
Inspect:
- absolute URLs scattered through code;
- endpoint methods;
- query/body encoding;
validateStatusoverrides;- raw
Map<String, dynamic>escaping API clients; ResponseorDioExceptionescaping repositories;- state-management objects constructing requests directly.
Cross-cutting behavior
Inventory:
- bearer injection;
- refresh endpoint/client;
- every interceptor and whether it is queued;
- retries and idempotency keys;
CancelTokenownership;- file transfers/progress;
- cookies/caches;
- logging/telemetry;
- certificate/proxy customization;
- Web-specific code;
- tests and fake adapters. Do not add a second competing mechanism until you understand the existing one.
Request lifecycle model
Reason about Dio requests in this order:
API client
→ BaseOptions + per-request Options + arguments
→ RequestOptions
→ request interceptors (FIFO)
→ request transform/body encoding
→ HttpClientAdapter
→ platform HTTP stack
→ response body
→ validateStatus
→ response transform
→ response interceptors (FIFO)
→ callerFailure paths normalize through DioException and then error interceptors in insertion order.
Important consequences:
- Interceptor response/error order is FIFO; do not assume reverse middleware order.
- A pre-canceled
CancelTokencan stop the request before transport begins. - Request interceptors may
next,resolve, orreject; complete exactly one handler path. validateStatuschanges whether a status becomes a normalResponseorDioException.badResponse.receiveDataWhenStatusErrormeans rejected statuses can still have transformed/decoded response data.RequestOptionsis the composed request contract; feature code normally should not construct it directly.
Default architecture
Prefer:
UI
→ state management
→ repository
→ typed API client / remote data source
→ Dio
→ serverUse responsibilities deliberately:
- UI: rendering, input, progress presentation, navigation.
- State management: feature intent and loading/success/failure state.
- Repository: domain-facing operations, cache/local composition, failure mapping.
- API client: endpoint method/path/query/body, DTO parsing, endpoint-specific options.
- Dio: transport, interceptors, transformation, cancellation, adapter. Avoid giant catch-all API services when feature/service-scoped clients reduce coupling.
Client selection gate
Reuse an existing Dio when origin and network policy match.
Create a distinct client when a material boundary differs, such as:
- backend/base URL;
- certificate/trust policy;
- proxy/adapter policy;
- refresh endpoint recursion isolation;
- radically different transfer/timeouts;
- ownership/lifecycle.
Do not create a new client merely because one endpoint is different. Prefer per-request
Optionsfor endpoint-specific behavior.
Options discipline
Use BaseOptions only for real client-wide defaults such as base URL, common Accept, coherent timeout defaults, shared redirect policy, or adapter-level assumptions.
Use request Options for endpoint-specific:
- response type;
- content type;
- unusual timeout;
- auth opt-out;
- retry/idempotency metadata;
- endpoint-specific headers;
- status acceptance;
- redirect policy.
Use
extrafor local transport metadata consumed by interceptors/transformers. Keep secrets out of generic metadata.
Do not globally force JSON content type if the client also sends multipart or other body types.
Authentication and refresh gate
Separate four concerns:
- secure token storage;
- refresh endpoint/client;
- dynamic bearer injection;
- application session invalidation.
For refresh:
- keep refresh requests out of the bearer-refresh recursion path;
- synchronize refresh work so concurrent
401s share one refresh operation; - compare the failed Authorization header with the currently stored token to detect that another request already refreshed;
- tag retried requests and permit at most the intended refresh retry;
- clear/invalidate session on terminal refresh failure;
- keep login navigation outside interceptors.
Prefer a shared refresh Future when only refresh work needs serialization. Use
QueuedInterceptoronly when serialized interceptor access itself is required.
Remember current queued semantics: request, response, and error queues are separate; it does not mean request A completes its entire lifecycle before request B starts.
Interceptor gate
Use interceptors for transport-wide concerns such as:
- current auth header;
- correlation/tracing metadata;
- language/tenant headers;
- request signing;
- cookies;
- bounded transport telemetry;
- tightly constrained refresh/retry behavior. Do not put:
- navigation;
- dialogs;
- feature state;
- business policy;
- DTO-to-domain mapping;
- unrelated endpoint orchestration inside interceptors.
Order interceptors deliberately. A signer must see the values it signs. A logger that should observe final request changes belongs after the modifying interceptors.
Error mapping gate
Handle all current DioExceptionType categories deliberately:
connectionTimeout;sendTimeout;receiveTimeout;transformTimeout;badCertificate;badResponse;cancel;connectionError;unknown. Map transport categories into stable application failures. Do not make widgets inspect Dio enums or raw response bodies.
Keep these distinctions:
- cancellation can be expected behavior;
- connection failure does not prove the user is offline;
- bad certificate is a security/transport failure and should not be blindly retried;
- malformed server payload is distinct from transport failure;
badResponsemeans the server answered but status validation rejected it. Preserve server correlation/request IDs where useful, without exposing sensitive bodies.
Timeout gate
Tune the timeout phase that actually failed:
connectTimeout: connection/opening;sendTimeout: outbound data/upload;receiveTimeout: waits for incoming response data/events;transformTimeout: response transformation. Do not copy one arbitrary tuple to every endpoint. Base values on backend latency, payload size, network conditions, interaction type, retry policy, and total user-visible deadline.
Retry and idempotency gate
Before any automatic retry, answer:
- Is the failure plausibly transient?
- Is replay safe by HTTP semantics and the actual backend contract?
- Did the server already possibly process the side effect?
- Is there an idempotency key or resumable protocol?
- Is retry bounded by attempts and total elapsed time?
Never automatically retry:
- cancellation;
- certificate failure;
- malformed/validation failures;
- arbitrary
403/404; - side-effecting POST/payment/upload operations without a backend idempotency contract.
Treat access-token
401as auth-refresh flow, not generic retry. RespectRetry-After/rate-limit policy for429where applicable. Use backoff/jitter for retryable transient failures.
Cancellation gate
Use CancelToken when work can become obsolete:
- search superseded by a new query;
- feature disposed;
- cancelable transfer;
- redundant predecessor request;
- shared group with one real lifetime. Do not share one token across unrelated requests. Fix duplicate trigger bugs in addition to canceling their consequences.
Payload and transfer gate
JSON and DTOs
Keep raw JSON at the data boundary. Validate required response fields and map to DTO/domain types deliberately.
Before custom JSON isolation/transformation, inspect current FusedTransformer behavior and measure. Large payloads may be better fixed with pagination/filtering than client-side parsing tricks.
Uploads
Use FormData/MultipartFile or streams appropriate to the platform. Create fresh multipart content per attempt; do not reuse finalized FormData blindly.
For large uploads:
- avoid loading the entire file into memory when path/stream APIs exist;
- support cancellation/progress;
- use server resumable/idempotent protocols when retry is required.
Downloads
On native, prefer download() or streamed file writes for large files instead of ResponseType.bytes.
For resume:
- send a valid
Rangerequest; - append only after verifying
206 Partial Content; - do not append a full
200 OKbody to a partial file. On Web, remember browser download behavior can buffer the full response and the browser controls final file location; do not promise native streaming-to-disk semantics.
Throttle/coalesce high-frequency progress updates before driving large UI rebuilds.
Web gate
Treat Flutter Web as browser networking:
- CORS is server/browser policy;
- client
Access-Control-Allow-*headers do not fix CORS; - TLS, redirects, HTTP protocol, cookies, and download location are browser-controlled;
- use
BrowserHttpClientAdapter(withCredentials: true)only when the server's credentialed CORS policy supports it; - native filesystem/proxy/certificate assumptions do not automatically apply;
- very large browser downloads may require a server/browser-native delivery design.
Security gate
Block release for any of these:
- blanket
badCertificateCallback => true; - production TLS validation disabled;
- confidential backend/API secrets embedded in the client;
- raw Authorization/Cookie/password/payment logging;
- development proxy/trust settings enabled in release;
- cross-origin redirect behavior that can leak credentials;
- unreviewed custom CA/pinning with no rotation/recovery plan. Use request signing only when the key architecture actually supports the intended trust model. A secret embedded in a distributed Flutter binary is not a confidential server secret.
Caching gate
Dio core is not a complete automatic response-cache architecture.
Choose cache by responsibility:
- repository memory cache for mapped domain data and feature freshness;
- disk cache for intentional persistence/offline behavior;
- standards-aware HTTP cache for
Cache-Control, ETag, validators, and304semantics. Cache identity must account for user/tenant/auth and representation-affecting headers. Never share private cached responses across security contexts merely because URLs match.
Performance gate
Prioritize meaningful costs:
- reuse clients and connections;
- cancel obsolete requests;
- eliminate duplicate requests;
- avoid unnecessary queued interceptor serialization;
- bound secure-storage or expensive interceptor work;
- reduce oversized payloads;
- stream large binaries;
- throttle progress/UI updates;
- disable sensitive/verbose production body logging;
- bound retry cost.
Do not replace adapters, transformers, or protocols because they appear more advanced. Measure the actual bottleneck first.
Testing gate
Prefer deterministic seams:
- API client tests: request shape, method/path/query/headers/body/options, response parsing, malformed payloads.
- Repository tests: DTO/domain mapping, failure mapping, cache/domain behavior.
- Interceptor tests: header injection, ordering, refresh, retry markers, concurrency.
- Adapter tests: inject a fake
HttpClientAdapter. - Auth concurrency test: several simultaneous
401s must produce one refresh and bounded retries. - Cancellation tests: pre-cancel, during transport, superseded search, expected cancellation UI semantics.
- Transfer tests: multipart keys/fresh instances, resume requires
206, Web-specific behavior where targeted. Run the repository's normal formatter/analyzer/test commands after changes.
Change workflow
For each networking change:
- document the backend contract;
- identify the security/auth policy;
- select the existing or new Dio client intentionally;
- choose base versus request-specific options;
- define request/response DTOs;
- implement the endpoint in a typed API client;
- validate the server payload;
- map through the repository boundary;
- decide cancellation ownership;
- decide retry/idempotency policy;
- verify refresh behavior if authenticated;
- add safe telemetry;
- add deterministic tests;
- review Web/platform differences;
- profile payload/interceptor/transfer cost if material;
- run format/analyze/tests.
Review output format
When reviewing a networking implementation, report:
Architecture
- client ownership and boundaries;
- API/repository layering;
- interceptor responsibilities.
Correctness
- request composition;
- status handling;
- DTO validation;
- cancellation/retry semantics.
Authentication and security
- token lifecycle;
- refresh concurrency;
- TLS/certificate/proxy/logging risks.
Reliability
- timeouts;
- idempotency;
- rate-limit handling;
- failure mapping.
Performance
- duplicate work;
- payload size;
- streaming/buffering;
- queued interceptor cost;
- transform/progress behavior.
Platform differences
- Web/CORS/cookies/downloads;
- native adapter/filesystem/TLS behavior.
Tests
- missing deterministic coverage;
- concurrency/cancellation/transfer cases.
Required changes
Order findings by severity and state the smallest safe fix.
Production definition of done
Approve the networking layer only when the applicable evidence shows:
- Dio clients are reused and owned coherently;
- base URLs and endpoint contracts are correct;
- request/global options are scoped correctly;
- DTO parsing validates server payloads;
DioExceptiondoes not leak into presentation code;- current access tokens are injected dynamically;
- refresh cannot recurse or fan out into many simultaneous refresh calls;
- retried auth requests are bounded;
- terminal refresh failure invalidates the session correctly;
- timeouts match operation classes;
- cancellation works for obsolete/long-running work;
- retry is bounded and side effects are idempotency-reviewed;
- multipart data is not reused unsafely;
- large native transfers avoid unnecessary whole-body buffering;
- Web behavior is browser-correct;
- TLS validation is intact;
- secrets are absent from logs and client-embedded confidential credentials;
- caches are separated by security context and have explicit semantics;
- interceptors remain transport-focused and concurrency-safe;
- performance changes have evidence when material;
- deterministic tests cover success, transport/server failure, malformed payload, auth refresh/concurrency, cancellation, and custom adapter/transfer behavior where used;
- the codebase uses current Dio 5.x names/APIs for its locked version. If a critical condition cannot be evidenced, report the layer as not approved for production and identify the missing verification.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

