{"product":"anthias","releases":[{"date":"2026-10-16","entries":[{"areas":[],"breaking":false,"content_html":"\u003cp\u003eOn a board short of memory, Anthias kept stopping and restarting parts of itself, which cost the\nboard time and memory it didn\u0026#39;t have. It was the largest single problem in the crash reports\nAnthias devices send the project. Anthias 2026.10.0 stops it, and upgrading is all you need to do.\u003c/p\u003e\n\u003cp\u003eAnthias runs uploads, downloads, video probing and housekeeping in a background worker, the\n\u003ccode\u003eanthias-celery\u003c/code\u003e container. That worker kept killing its own idle processes and starting\nreplacements. Its log filled with lines like these:\u003c/p\u003e\n\u003cdiv class=\"code-block\"\u003e\n  \u003cbutton type=\"button\" class=\"code-copy\" aria-label=\"Copy code\" data-copy-code\u003e\n    \u003csvg data-copy viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\n      \u003crect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\"\u003e\u003c/rect\u003e\n      \u003cpath d=\"M5 15V5a2 2 0 0 1 2-2h10\"\u003e\u003c/path\u003e\n    \u003c/svg\u003e\n    \u003csvg data-check viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\u003e\n      \u003cpath d=\"M20 6 9 17l-5-5\"\u003e\u003c/path\u003e\n    \u003c/svg\u003e\n  \u003c/button\u003e\n  \u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eProcess \u0026#39;ForkPoolWorker-3\u0026#39; pid:412 exited with \u0026#39;exitcode 1\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTimed out waiting for UP message from \u0026lt;ForkProcess(ForkPoolWorker-4, started daemon)\u0026gt;\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/div\u003e\n\u003cp\u003eThe trigger was the soft time limit, the warning a task gets before its hard limit cuts it off. On a\nbusy board that warning could arrive after the task had already finished, and the idle process that\nreceived it exited. From Anthias 2026.10.0, a warning that arrives when no task is running, or that\nwas meant for an earlier task, is ignored. A task that really runs past its soft limit is still\nstopped, and one that hangs is still cut off by its hard limit.\u003c/p\u003e\n\u003cp\u003eThe tasks that read the display\u0026#39;s power state over HDMI-CEC and send telemetry could also catch the\nwarning meant for them, carry on, and get killed by the hard limit. They now stop when they\u0026#39;re told\nto.\u003c/p\u003e\n","description":"On a board short of memory, the background worker no longer kills and restarts its own idle processes, which cost the board time and memory it didn't have. It was the largest single problem in the crash reports Anthias devices send the project.","title":"The background worker stops killing its own processes","type":"fix","url":"https://www.screenly.io/releases/anthias/2026.10.0/worker-stops-killing-its-own-processes/"},{"areas":[],"breaking":false,"content_html":"\u003cp\u003eRestoring a backup from the Settings page could leave Anthias with a database it couldn\u0026#39;t read, or\none so locked that the web interface answered with server errors. A player upgraded from an older\ninstall could hit the second one too. Anthias 2026.10.0 fixes both, and backups made by earlier\nversions still restore.\u003c/p\u003e\n\u003cp\u003eBoth problems were in the one SQLite database where Anthias keeps its assets and settings,\n\u003ccode\u003e~/.anthias/anthias.db\u003c/code\u003e, which the web server, the background worker and the viewer all use at\nonce.\u003c/p\u003e\n\u003ch2 id=\"backups-and-restores\"\u003eBackups and restores\u003c/h2\u003e\n\u003cp\u003e\u0026quot;Get backup\u0026quot;, under Backup \u0026amp; restore in Settings, used to put the database in the archive together\nwith its write-ahead log files, \u003ccode\u003eanthias.db-wal\u003c/code\u003e and \u003ccode\u003eanthias.db-shm\u003c/code\u003e, each read at a different\nmoment while Anthias kept writing. \u0026quot;Upload \u0026amp; recover\u0026quot; then unpacked the archive over the live\nfiles. When the archive carried no log of its own, the old database\u0026#39;s log stayed next to the\nrestored database, SQLite replayed it into the wrong file, and the first read after the restore\nfailed with \u003ccode\u003edatabase disk image is malformed\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eNow a backup carries a single copy of the database, taken through SQLite at one moment, with\neverything in the log included and no log files beside it. A restore deletes the log files of each\ndatabase it replaces before anything opens it.\u003c/p\u003e\n\u003cp\u003eBackups made before 2026.10.0 still restore. Their log files are skipped, which avoids the\ncorruption but leaves out any changes that were still only in the log when the backup was made.\u003c/p\u003e\n\u003cp\u003eIf the database can\u0026#39;t be copied while its log holds changes that aren\u0026#39;t in the main file yet, the\nbackup now fails, and the \u0026quot;Get backup\u0026quot; download ends in an error, instead of producing an archive\nwithout those changes.\u003c/p\u003e\n\u003ch2 id=\"a-database-that-hasn39t-switched-to-write-ahead-logging\"\u003eA database that hasn\u0026#39;t switched to write-ahead logging\u003c/h2\u003e\n\u003cp\u003eAnthias runs the database with write-ahead logging, so reads and writes don\u0026#39;t block each other. It\nused to ask SQLite to switch to that mode every time it opened a connection. On a database that\nwasn\u0026#39;t switched yet, such as one from an older install or one just restored, the switch needs the\nfile to itself, and with 3 services using it the request failed with \u003ccode\u003edatabase is locked\u003c/code\u003e. Each\nfailure left a file open, and the web interface answered with server errors. In the project\u0026#39;s crash\nreports, one device went from \u003ccode\u003edatabase is locked\u003c/code\u003e to \u003ccode\u003eToo many open files\u003c/code\u003e to\n\u003ccode\u003eunable to open database file\u003c/code\u003e in a single afternoon.\u003c/p\u003e\n\u003cp\u003eNow each service checks the mode once when it starts, and switches it if it can. If the database is\nbusy, Anthias carries on in the old mode, which is slower when several services write at once but\nworks, and tries again at the next start.\u003c/p\u003e\n","description":"Restoring a backup could leave Anthias with a database it couldn't read, or one so locked that the web interface answered with server errors. Backups now hold a single consistent copy of the database, and Anthias starts cleanly on a just-restored or older database.","title":"Restoring a backup no longer corrupts or locks up the database","type":"fix","url":"https://www.screenly.io/releases/anthias/2026.10.0/database-backups-restores-and-startup/"},{"areas":[],"breaking":false,"content_html":"\u003cp\u003eWhile Anthias prepares an upload or downloads a video, the asset shows \u0026quot;Processing\u0026quot; in the asset\ntable. If that fails, the row shows \u0026quot;Failed\u0026quot;, and clicking it opens the asset with the reason.\nAnthias 2026.10.0 fixes the cases where a slow job never got that far.\u003c/p\u003e\n\u003ch2 id=\"jobs-that-run-too-long\"\u003eJobs that run too long\u003c/h2\u003e\n\u003cp\u003eFive of these jobs had only a hard time limit: reading a video\u0026#39;s duration, preparing an image,\npreparing a video, downloading from YouTube and downloading a video from a URL. One that ran over\nwas killed on the spot with no chance to update the asset, so the asset stayed on \u0026quot;Processing\u0026quot; with\nnothing to say why.\u003c/p\u003e\n\u003cp\u003eFrom Anthias 2026.10.0, each of them gets a warning 30 seconds before its hard limit and stops\ncleanly. An image or video that runs out of time while being prepared or downloaded shows \u0026quot;Failed\u0026quot;\nwith a message such as \u0026quot;Timed out: processing did not finish within 270s\u0026quot;. A video whose duration\ncan\u0026#39;t be read in time leaves \u0026quot;Processing\u0026quot; without a message. The limits themselves are the same as\nbefore: 2 minutes to read a video\u0026#39;s duration or prepare a video, 5 minutes to prepare an image, and\n15 minutes for a download.\u003c/p\u003e\n\u003ch2 id=\"images-over-the-size-limit\"\u003eImages over the size limit\u003c/h2\u003e\n\u003cp\u003eAnthias refuses images over 50 megapixels. An image between 50 and 100 megapixels already said so,\nin a message written for developers. One over 100 megapixels, such as a large scan or a poster\nexport, failed with the image library\u0026#39;s own warning about a possible \u0026quot;decompression bomb DOS\nattack\u0026quot;, which sounds far worse than an image that\u0026#39;s too big. Now both say how big the image is,\nthat the limit is 50,000,000 pixels, and to resize it and upload again.\u003c/p\u003e\n\u003ch2 id=\"expected-failures-stop-looking-like-crashes\"\u003eExpected failures stop looking like crashes\u003c/h2\u003e\n\u003cp\u003eA YouTube link that YouTube refuses (a 403 or 404, an age restriction, a region block), an image\nover the limit, and a source file that\u0026#39;s gone by the time processing starts, for example because\nyou deleted the asset while it was processing, are expected outcomes. The worker log now records\nthem as a single line instead of an error with a traceback, and they\u0026#39;re no longer sent as crash\nreports. If you point crash reporting at your own Sentry project with \u003ccode\u003eSENTRY_DSN\u003c/code\u003e, they stop\nshowing up there too. The asset table shows the same as before: a YouTube refusal still shows\n\u0026quot;Failed\u0026quot; with YouTube\u0026#39;s reason, and a deleted asset is gone.\u003c/p\u003e\n","description":"When preparing or downloading an asset runs out of time, Anthias 2026.10.0 marks it Failed with a timeout message instead of leaving it on Processing, and an image over the 50 megapixel limit says to resize it.","title":"Media that takes too long to process no longer stays on Processing","type":"fix","url":"https://www.screenly.io/releases/anthias/2026.10.0/assets-that-fail-say-why/"},{"areas":[],"breaking":false,"content_html":"\u003cp\u003eThe viewer is the container that puts content on the screen. Anthias 2026.10.0 fixes 4 ways it\ncould get stuck starting up.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eOn a slow first boot, or right after a restore, the viewer could ask for the asset table before\nthe database had its tables. It failed with \u003ccode\u003eno such table: assets\u003c/code\u003e and the container restarted\ninto the same race. The viewer now waits until the database is fully set up, and logs\n\u003ccode\u003eDatabase is not migrated yet; delaying viewer startup\u003c/code\u003e every 30 seconds while it waits.\u003c/li\u003e\n\u003cli\u003eIf an earlier display process was still holding the \u003ccode\u003eanthias.viewer\u003c/code\u003e name on the session bus,\nevery new attempt to start one failed within half a second, and the viewer spent all 30 of its\nattempts on the same failure. In the project\u0026#39;s testing on a Pi 5 that was close to 7 minutes of\nblack screen. The viewer now finds the old process, asks it to exit, forces it if it won\u0026#39;t, and\nstarts the new one.\u003c/li\u003e\n\u003cli\u003eOn the boards that run the Wayland compositor (Pi 5, x86 and arm64), the viewer used to treat a\nleftover socket from a compositor that had died as a running one, and gave up before the\ncompositor came back. It now connects to the socket and waits until the compositor answers.\u003c/li\u003e\n\u003cli\u003eChanging \u0026quot;Screen rotation\u0026quot; or \u0026quot;Prefer dark mode\u0026quot; in Settings restarts the display process. The\nviewer now waits for the old one to exit before loading the next asset, instead of sending the\nasset to a process that was on its way out and stalling until it dropped off.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"clearer-errors-when-the-display-process-won39t-start\"\u003eClearer errors when the display process won\u0026#39;t start\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eWhen the display process dies before it finishes starting, the viewer\u0026#39;s error now says how it\nended, such as \u003ccode\u003ekilled by SIGSEGV (-11)\u003c/code\u003e. Before, it ended on whatever the process last printed.\u003c/li\u003e\n\u003cli\u003eOn the Pi 5, x86 and arm64 images, a display process that can\u0026#39;t register on the session bus\nexits with status 1 and says which registration failed. It used to crash with SIGSEGV on the way\nout, which looked like a crash in the display process.\u003c/li\u003e\n\u003cli\u003eA display process that crashes now prints a stack trace on every board, which the viewer\u0026#39;s error\nincludes when the crash happens during startup. Before, only the 64-bit Pi 3 image printed one.\u003c/li\u003e\n\u003c/ul\u003e\n","description":"After a restore, a slow first boot or a change to screen rotation, a player could sit on a black screen while the viewer kept failing to start. Anthias 2026.10.0 fixes 4 ways it got stuck, and when the display process does fail, the error now says how it ended.","title":"The viewer starts more reliably after restores, slow boots and display restarts","type":"fix","url":"https://www.screenly.io/releases/anthias/2026.10.0/viewer-starts-more-reliably/"},{"areas":[],"breaking":false,"content_html":"\u003cp\u003eTwo screens in a shop cycling the same menu board in German and English used to drift apart, until\nafter a few hours they switched languages seconds apart. The player started an asset\u0026#39;s countdown\nonly after it had refreshed the schedule, read the database and told the display to load the asset,\nso each rotation took the asset\u0026#39;s duration plus that overhead, and the overhead differs from one\ndevice to the next.\u003c/p\u003e\n\u003cp\u003eFrom Anthias 2026.10.0, the countdown starts when the rotation does, so an image or web page with a\n30 second duration rotates 30 seconds after its rotation began. If loading takes longer than a short\nasset\u0026#39;s duration, the player moves straight on to the next one. The viewer log shows the wait next\nto the duration, for example \u003ccode\u003eSleeping for 29.8 of 30s\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eA video\u0026#39;s duration is its length, so the overhead now comes off the end of the clip instead: the\nlast fraction of a second can be cut, more on a slow board. Stopping a video still adds time to each\nrotation, so a playlist with videos still drifts, more slowly than before. In the project\u0026#39;s testing\non a Pi 2 with a mixed playlist, drift went from about 36 seconds an hour to about 28.5.\u003c/p\u003e\n\u003cp\u003ePlayers still don\u0026#39;t line up with each other: each one starts its playlist when it boots.\u003c/p\u003e\n","description":"An image or web page now rotates when its duration is up, counted from the start of the rotation rather than after the player's own overhead, so screens showing the same playlist stay in step for longer.","title":"Players showing the same playlist drift apart less","type":"fix","url":"https://www.screenly.io/releases/anthias/2026.10.0/playlist-rotation-timing/"},{"areas":[],"breaking":false,"content_html":"\u003ch2 id=\"fixes\"\u003eFixes\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRunning \u003ccode\u003ebin/upgrade_containers.sh\u003c/code\u003e yourself on a board with less than 1.5 GiB of memory, such as\na Pi 2 or Pi 3, now stops the viewer and the background worker before pulling new images, and\nstarts them again on the new ones. Pulling with the viewer running could use up memory and swap\nand reset the board halfway through. The screen shows no content during the pull, and the web\ninterface stays up. Upgrades through the installer already stopped every container first.\u003c/li\u003e\n\u003cli\u003eA memory card whose product name contains a byte that isn\u0026#39;t valid UTF-8 no longer stops storage\nhealth monitoring, which the storage card on the System Info page relies on.\u003c/li\u003e\n\u003cli\u003eStarting the viewer no longer logs \u003ccode\u003e/proc/\u0026lt;pid\u0026gt;/oom_score_adj: No such file or directory\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"for-contributors\"\u003eFor contributors\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eA test fails the build if a background task has a hard time limit without a soft one below it,\nand another fails it if a module the viewer imports pulls in celery, which the viewer image\ndoesn\u0026#39;t ship.\u003c/li\u003e\n\u003cli\u003eNew tests cover the soft time limit handling, the database readiness wait, the viewer\u0026#39;s startup\nand respawn paths, and SQLite backup and restore.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ePython, JavaScript and GitHub Actions dependencies are updated.\u003c/p\u003e\n","description":"A memory card with an unusual product name no longer turns off storage health monitoring, and starting the viewer no longer logs an error about a missing process file.","title":"The upgrade script no longer runs a Pi 2 or Pi 3 out of memory, and other fixes","type":"roundup","url":"https://www.screenly.io/releases/anthias/2026.10.0/fixes-and-improvements/"}],"json":"https://www.screenly.io/releases/anthias/2026.10.0/v1.json","product":"anthias","product_label":"Anthias","url":"https://www.screenly.io/releases/anthias/2026.10.0/","version":"2026.10.0"}],"title":"Anthias 2026.10.0","url":"https://www.screenly.io/releases/anthias/2026.10.0/","version":1}