Rules¶
Azure Functions Doctor executes declarative rules from a JSON ruleset.
Built-in rules are defined in:
src/azure_functions_doctor/assets/rules/v2.json
You can replace the built-in set with --rules <file>.
Rule execution model¶
Each rule contains:
- identity (
id,label) - grouping (
category,section) - behavior (
type,condition) - severity intent (
required) - ordering (
check_order) - remediation (
hint, optionalhint_url)
Rules are validated by:
src/azure_functions_doctor/schemas/rules.schema.json
Required vs optional¶
required: true+ raw handler fail -> item statusfailrequired: false+ raw handler fail -> item statuswarn
Only required failures produce non-zero process exit code.
Built-in rule types¶
The built-in ruleset uses the following handler types:
compare_versionpath_existsfile_existsdependency_manifestpackage_declaredpackage_forbiddennative_dependency_risksource_code_containsblueprint_registrationconditional_existscallable_detectionexecutable_existsany_of_existsfile_glob_checkhost_json_propertyhost_json_versionhost_json_extension_bundle_versionlocal_settings_securitydecorator_orderendpoint_metadataopenapi_version_mixingscan_before_speclanggraph_anonymous_authdurable_nondeterminismunsupported_metadata_versionotel_activation
For the authoritative, script-generated list of every built-in rule and its type, see the Rule Inventory.
Rule-by-rule reference¶
1) check_programming_model_v2¶
- What it checks: Source contains Azure Functions decorator usage (
@app.) via AST detection. - Why it matters: Doctor targets Python v2 projects; this check protects model compatibility.
- How to fix: Use
func.FunctionApp()and decorator-based triggers.
Example failing detail:
2) check_blueprint_registration¶
- What it checks: Blueprint aliases declared with
func.Blueprint()and used in decorators are also registered viaapp.register_functions(bp)somewhere in the project. Only the official Azure Functions Python v2 API is recognized; Flask/FastAPI-styleregister_blueprint(...)calls are not treated as registration. - Why it matters: Unregistered Blueprints look valid in code but their routes never index at runtime.
- How to fix: Register each Blueprint on your
FunctionApp, typically fromfunction_app.py.
Example warning detail:
Detected:
- bp = func.Blueprint()
- @bp.route(...)
Missing:
- app.register_functions(bp)
Fix: add `app.register_functions(bp)` in function_app.py.
3) check_python_version¶
- What it checks: Python version evaluated for the app target is
>=3.10. - Why it matters: Azure Functions Python runtime compatibility depends on the deployed target version, not just the interpreter running the doctor.
- How to fix: Use Python 3.10+ locally and in CI, or pass
--target-python <3.10|3.11|3.12|3.13|3.14>when your deploy target differs from the tool runtime. Note that on the Linux Consumption plan the maximum supported runtime is Python 3.12.
Example output:
With override:
4) check_venv¶
- What it checks: A virtual environment is activated — any of
VIRTUAL_ENV,CONDA_PREFIX, orUV_PROJECT_ENVIRONMENTis set (venv, conda, or uv). - Why it matters: Virtual environments reduce dependency drift and environment pollution.
- How to fix: Create and activate a virtual environment (
.venv, conda, or uv) before running diagnostics.
Example failing detail:
5) check_python_executable¶
- What it checks:
sys.executablepoints to an existing path. - Why it matters: Broken interpreter paths indicate unstable runtime environment.
- How to fix: Reinstall or reactivate Python environment.
Example detail:
6) check_requirements_txt¶
- What it checks: Dependencies are declared via
requirements.txtorpyproject.tomlat the project root. - Why it matters: Deployability and reproducibility depend on declared dependencies.
- How to fix: Add
requirements.txt(or declare dependencies inpyproject.toml) and include runtime dependencies.
Example failing detail:
7) check_azure_functions_library¶
- What it checks:
azure-functionsis declared inrequirements.txtorpyproject.toml. - Why it matters: Function app code depends on Azure Functions Python library.
- How to fix: Add
azure-functionsto dependency declarations.
Example failing detail:
8) check_native_dependency_risk¶
- What it checks:
requirements.txtfor packages with common native-extension deployment risk. - Why it matters: These packages are valid, but Azure Functions Python deployments often fail when Linux wheels or system libraries do not match the build environment.
- How to fix: Build against the Azure Functions Linux runtime. Prefer remote build with
func azure functionapp publish --build remote. - Current package list:
pyodbc,cryptography,lxml,pillow,numpy,pandas,scipy,opencv-python,psycopg2,grpcio,ujson,orjson. - Severity: Warning only (
required: false). It never produces a hard failure.
Example warning detail:
Native dependencies detected: pyodbc, pillow
These packages depend on platform-specific native libraries.
Ensure your build environment matches the Azure Functions Linux runtime.
Recommended: use remote build (`func azure functionapp publish --build remote`).
- pyodbc: requires unixODBC and a matching wheel
- pillow: ensure libjpeg/zlib-compatible wheels for Linux deployment
9) check_host_json¶
- What it checks:
host.jsonexists at project root. - Why it matters: Azure Functions host configuration is required for valid app structure.
- How to fix: Add a valid
host.json(at minimum{ "version": "2.0" }).
Example failing detail:
10) check_local_settings¶
- What it checks:
local.settings.jsonexists. - Why it matters: Local development often needs this file for settings and connection values.
- How to fix: Create local settings file for local runs (do not commit secrets).
Example warning detail:
11) check_func_cli¶
- What it checks:
funcexecutable is available onPATH. - Why it matters: Core Tools enable local hosting and rich runtime tooling.
- How to fix: Install Azure Functions Core Tools v4+.
Example warning detail:
12) check_func_core_tools_version¶
- What it checks: Core Tools version is
>=4.0. - Why it matters: Older versions can diverge from current host/runtime expectations.
- How to fix: Upgrade Core Tools installation.
Example warning detail:
13) check_durabletask_config¶
- What it checks: If durable usage is detected in source,
$.extensions.durableTaskexists inhost.json. - Why it matters: Durable Functions need matching host configuration.
- How to fix: Add durableTask configuration when using durable features.
Example details:
or
14) check_app_insights¶
- What it checks: Application Insights uses a connection string
(
APPLICATIONINSIGHTS_CONNECTION_STRING). A legacy instrumentation key (APPINSIGHTS_INSTRUMENTATIONKEYorhost.json:instrumentationKey) is treated as stale, andAPPLICATIONINSIGHTS_AUTHENTICATION_STRINGis recognised for Entra (AAD) authentication. - Why it matters: Instrumentation-key ingestion ended 2025-03-31, so a connection string is required for telemetry to reach Application Insights.
- How to fix: Set
APPLICATIONINSIGHTS_CONNECTION_STRINGand remove any legacy instrumentation key.
Example warning detail:
Application Insights is not configured; set APPLICATIONINSIGHTS_CONNECTION_STRING to enable telemetry. (optional)
15) check_extension_bundle¶
- What it checks:
$.extensionBundleexists inhost.json. - Why it matters: Extension bundles help ensure binding dependencies are available.
- How to fix: Add extensionBundle section to host config.
Example warning detail:
16) check_asgi_wsgi_exposure¶
- What it checks: Whether an ASGI/WSGI framework (FastAPI/Flask/Starlette/Quart)
is wired into Azure Functions via
AsgiFunctionApp/WsgiFunctionApp(orAsgiMiddleware/WsgiMiddleware). - Why it matters: A plain decorator-based
FunctionApphas no ASGI/WSGI app, so the check skips to avoid noise. A detected framework that is not exposed is a real wiring gap. - How to fix: Expose the framework callable with
AsgiFunctionApp/WsgiFunctionApp.
Example warning detail:
ASGI/WSGI framework detected but no callable is exposed via AsgiFunctionApp/WsgiFunctionApp (or AsgiMiddleware/WsgiMiddleware); wire it into Azure Functions: ['main.py:\bFastAPI\s*\('] (optional)
17) check_unused_files¶
- What it checks: Presence of unwanted patterns (for example
**/*.pyc,**/__pycache__,.venv,tests/). - Why it matters: Reduces deployment package clutter and risk.
- How to fix: Clean or exclude unwanted files from deployment artifacts.
Example warning detail:
18) check_azure_functions_worker¶
- What it checks:
azure-functions-workeris not declared inrequirements.txt. - Why it matters: The Azure Functions platform manages the worker runtime; pinning it can cause deployment failures.
- How to fix: Remove
azure-functions-workerfrom your dependency declarations. - Severity: Warning only (
required: false).
19) check_host_json_version¶
- What it checks:
host.jsondeclares"version": "2.0"as required by the v2 runtime. - Why it matters: An incorrect or missing host version breaks v2 app indexing.
- How to fix: Set
{ "version": "2.0" }inhost.json. - Severity: Required (
required: true).
20) check_funcignore¶
- What it checks: A
.funcignorefile is present to control what gets deployed. - Why it matters: Without it, unnecessary files can bloat the deployment package.
- How to fix: Add a
.funcignorefile excluding local-only paths. - Severity: Warning only (
required: false).
21) check_local_settings_git_tracked¶
- What it checks:
local.settings.jsonis not tracked by git. - Why it matters: Tracking it can leak secrets into version control.
- How to fix: Add
local.settings.jsonto.gitignoreand untrack it. - Severity: Warning only (
required: false).
22) check_extension_bundle_v4¶
- What it checks:
extensionBundleinhost.jsonuses a documented v4 range. The range is parsed as an interval (not a string prefix): the lower bound must be an inclusive major 4 ([4.0.0or[4.*) and the upper bound must be an exclusive5.0.0). Over-broad ranges such as[4.0.0, 6.0.0)are rejected. The bundle id must beMicrosoft.Azure.Functions.ExtensionBundle. - Why it matters: Aligns binding extensions with the current supported bundle.
- How to fix: Update the
extensionBundle.versionrange to the v4 range. - Severity: Warning only (
required: false).
23) check_decorator_order¶
- What it checks:
@validate_httpis not stacked outside@with_context. The correct order (top to bottom) is@app.route→@with_context→@validate_http. - Why it matters: Incorrect decorator order changes request handling behavior.
- How to fix: Reorder decorators so
@with_contextwraps@validate_http. - Severity: Warning only (
required: false).
24) check_endpoint_metadata¶
- What it checks: In projects depending on
azure-functions-validation, HTTP route handlers emit endpoint OpenAPI metadata via@validate_httpor another supported metadata decorator (@openapi, LangGraph metadata). Routes annotated with those decorators are not flagged even without@validate_http. - Why it matters: Handlers without it will not appear in generated OpenAPI specs.
- How to fix: Apply
@validate_http— or another supported endpoint-metadata decorator (@openapior the LangGraph metadata decorators) — to route handlers that should emit metadata. - Severity: Warning only (
required: false).
25) check_openapi_version_mixing¶
- What it checks: A project does not mix two or more OpenAPI versions. It recognizes 3.0 signals (3.0.x version strings or the
nullablekeyword), 3.1 signals (3.1.x strings), and 3.2 signals (3.2.x strings). A single-version project — including 3.2-only — never warns. - Why it matters: Mixing versions produces inconsistent generated specs.
- How to fix: Standardize on a single OpenAPI version across the project.
- Severity: Warning only (
required: false).
26) check_scan_before_spec¶
- What it checks: The OpenAPI spec is not built before endpoints are scanned/registered (and not built without any endpoint scan).
- Why it matters: Building the spec too early yields an empty or incomplete spec.
- How to fix: Scan/register endpoints before building the spec.
- Severity: Warning only (
required: false).
27) check_langgraph_anonymous_auth¶
- What it checks: In projects that import
langgraph, HTTP routes do not useauth_levelset toANONYMOUS. - Why it matters: Anonymous auth leaves graph endpoints publicly reachable.
- How to fix: Set a non-anonymous
auth_levelfor LangGraph HTTP routes. - Severity: Warning only (
required: false).
28) check_durable_nondeterminism¶
- What it checks: Orchestration or entity trigger functions do not call nondeterministic APIs (
datetime.now,random,uuid,requests,open,os.getenv). - Why it matters: Nondeterministic calls break Durable Functions replay.
- How to fix: Move nondeterministic work into activity functions.
- Severity: Required (
required: true).
29) check_otel_trace_context_activation¶
- What it checks: In projects that opt into
azure-functions-loggingtrace-context activation (activate_trace_context=Trueorset_default_trace_context_activation), anopentelemetrydistribution is declared inrequirements.txtorpyproject.toml. - Why it matters:
azure-functions-loggingsilently degrades activation to a no-op when OpenTelemetry is unavailable, so requested trace context is dropped without any runtime error. - How to fix: Install the
azure-functions-logging[otel]extra (or anopentelemetry-*package), or disableactivate_trace_context. - Severity: Warning only (
required: false).
Deploy-risk rule reference¶
The runtime/hosting/deployment-correctness rules also have individual reference pages under docs/rules/. Each page shows the exact finding text, so searching for an error message lands directly on the rule:
- Python runtime lifecycle
- Functions runtime lifecycle
- Hosting plan lifecycle
- Flex Consumption runtime config
- Flex Consumption deprecated app settings
- Flex Consumption deployment storage
- Binding connection resolution
- Functions extension version
- Linux runtime (linuxFxVersion)
- Dev-storage emulator connection
- Pinned requirements
Experimental-tier and integration-group rules are intentionally not given per-rule pages yet (see #326).
Rule authoring template¶
{
"id": "check_example",
"category": "structure",
"section": "project_structure",
"label": "host.json",
"description": "Checks host.json exists.",
"type": "file_exists",
"required": true,
"condition": {
"target": "host.json"
},
"hint": "Add host.json to project root.",
"check_order": 10
}
Guidance for custom rules¶
- Keep IDs stable and descriptive
- Use deterministic
check_ordervalues - Start policy experiments as optional rules
- Promote to required only after false-positive review
- Include clear
hinttext for faster remediation
Custom rules docs: Examples: Custom Rules
Safety and trust model¶
Rules may inspect local files, source code, environment variables, executable presence, and importable modules.
Warning
Only run trusted custom rules files, especially in shared CI environments.