{"record":{"id":"25b5e090a0a61fc6","repo":"nginx/nginx","slug":"ngx-log-alert-25b5e0","errorCode":"NGX_LOG_ALERT","errorMessage":"<ngx_directio_on_n> \\\"%s\\\" failed","messagePattern":"<ngx_directio_on_n> \\\\\"(.+?)\\\\\" failed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/http/modules/ngx_http_mp4_module.c","lineNumber":667,"sourceCode":"            }\n\n            ngx_pfree(r->pool, mp4);\n\n            return NGX_HTTP_INTERNAL_SERVER_ERROR;\n        }\n    }\n\n    log->action = \"sending mp4 to client\";\n\n    if (clcf->directio <= of.size) {\n\n        /*\n         * DIRECTIO is set on transfer only\n         * to allow kernel to cache \"moov\" atom\n         */\n\n        if (ngx_directio_on(of.fd) == NGX_FILE_ERROR) {\n            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,\n                          ngx_directio_on_n \" \\\"%s\\\" failed\", path.data);\n        }\n\n        of.is_directio = 1;\n\n        if (mp4) {\n            mp4->file.directio = 1;\n        }\n    }\n\n    r->headers_out.status = NGX_HTTP_OK;\n    r->headers_out.last_modified_time = of.mtime;\n\n    if (ngx_http_set_etag(r) != NGX_OK) {\n        return NGX_HTTP_INTERNAL_SERVER_ERROR;\n    }\n\n    if (ngx_http_set_content_type(r) != NGX_OK) {","sourceCodeStart":649,"sourceCodeEnd":685,"githubUrl":"https://github.com/nginx/nginx/blob/3f6f7824d4e2eb1ac37dec76683d525ac0ff521c/src/http/modules/ngx_http_mp4_module.c#L649-L685","documentation":"When a `directio <size>` threshold is configured and the file is at least that large, the module enables O_DIRECT on the file descriptor (ngx_directio_on) so the kernel cache is not polluted by the streaming transfer. If the filesystem rejects O_DIRECT, the call fails and this ALERT is logged; the transfer still proceeds on this code path.","triggerScenarios":"Serving an mp4 at or above the directio threshold from a filesystem without O_DIRECT support: tmpfs (/dev/shm), many FUSE mounts, some NFS configurations, certain container overlay setups.","commonSituations":"`directio 4m;` copied from static-file tuning guides while the videos actually live on tmpfs or an exotic mount; moving data dirs to /dev/shm for speed without revisiting directio settings.","solutions":["Set `directio off;` (the default) in the mp4 location unless benchmarking on the real filesystem shows a win.","Or move the media to a filesystem with O_DIRECT support such as ext4 or xfs.","If you keep directio, accept the ALERT per file but confirm responses still stream correctly; silence noise by disabling the directive."],"exampleFix":"# before\nlocation ~ \\.mp4$ {\n    mp4;\n    directio 4m;      # ALERT: files sit on tmpfs without O_DIRECT\n}\n\n# after\nlocation ~ \\.mp4$ {\n    mp4;\n    directio off;     # default; kernel caching of moov stays enabled\n}","handlingStrategy":"validation","validationCode":"# probe O_DIRECT support on the serving filesystem before enabling directio\npython3 - <<'PY'\nimport os\ntry:\n    fd = os.open('/data/videos/a.mp4', os.O_RDONLY | os.O_DIRECT)\n    print('O_DIRECT supported'); os.close(fd)\nexcept OSError as e:\n    print('O_DIRECT failed:', e)   # errno 22/25 -> keep directio off\nPY","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Leave directio off unless a benchmark on the production filesystem proves a win.","Re-check the directio setting whenever the media directory moves to new storage.","Treat ALERT-level directio messages as a signal the storage changed under the config."],"tags":["nginx","mp4","directio","filesystem","performance"],"backgroundTag":"directio-unsupported","analyzedSha":"3f6f7824d4e2eb1ac37dec76683d525ac0ff521c","analyzedAt":"2026-08-22T03:09:46.447Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}