Skip to main content

#364 CRE8 Social v5.1.4 Upgrade — Critical Installer Failures

Posted in ‘EasySocial’
This is a public ticket

Everybody will be able to see its contents. Do not include usernames, passwords or any other sensitive information.

Latest post by CreativeGraphics Support on Tuesday, 08 September 2026 09:36 UTC

markusberwing
Summary

Upgrading EasySocial to v5.1.4  caused a complete site outage — both frontend and backend were inaccessible for over an hour. The installation process stalled during "Extracting Files" / "Copying Files" and left the site in a broken state. Recovery required extensive manual intervention via SSH, including manually extracting nested ZIP archives, copying files to their correct destinations, and patching multiple installer controller files to bypass broken installation steps.

This ticket documents three architectural flaws in the EasySocial installer that caused this situation and made recovery unnecessarily difficult.

Issue 1: Installer Deletes the Source ZIP Before Installation Completes

File: administrator/components/com_easysocial/setup/controllers/installation.extract.php

Problem: The execute() method deletes the component ZIP package (com_easysocial_BGv5.1.4_pro.zip) from the setup/packages/ directory immediately after extraction — regardless of whether the subsequent installation steps succeed:

php

// Line from installation.extract.php @File::delete($storage);

If the extract step times out, or if any subsequent step (Copying Files, Installing Applications, etc.) fails, the ZIP is already gone. The installer cannot retry because the source package no longer exists. The only recovery path is to manually re-upload and re-place the ZIP file via SSH.

Expected behavior: The ZIP should only be deleted after the entire installation process has completed successfully (i.e., after "Post Installation Cleanup"), not after the extract step. Alternatively, the ZIP should never be deleted — the admin can clean it up manually, or a cleanup step can handle it.

Issue 2: "Copying Files" Step Has No Batching, Resume, or Timeout Handling

File: administrator/components/com_easysocial/setup/controllers/installation.copy.php

Problem: The copy step attempts to extract and copy all component files (admin, site, media, plugins, modules, languages — thousands of files) within a single HTTP request. On servers with standard PHP timeout settings (even with max_execution_time = 600), this request stalls and eventually times out. There is no:

  • Batching: The step does not process files in chunks across multiple AJAX calls (unlike "Installing Applications," which does work in batches).
  • Resume capability: If the request times out mid-copy, there is no way to resume. The installer shows the warning icon but clicking "Retry" starts the entire copy process from scratch — which also times out.
  • Progress tracking: There is no indication of which files have been copied and which haven't.

The result is a half-installed component: some PHP files are present, but critical configuration files like defaults/site.json and defaults/users/social.params.json are missing.

Expected behavior: The copy step should work in batches (e.g., one sub-package at a time: admin, site, media, plugins, modules), with each batch processed in a separate AJAX request — exactly as the "Installing Applications" step already does. Each batch should verify completion before proceeding to the next.

Issue 3: Missing site.json Causes Complete Site Outage With No Fallback

File: administrator/components/com_easysocial/includes/config/config.php (line 89)

Problem: When the installation fails mid-copy and defaults/site.json is not present, EasySocial throws a fatal error on every page load — both frontend and backend:

An error has occurred. 0 Invalid json syntax in site.json

This error is not limited to EasySocial pages. Because EasySocial hooks into Joomla via system plugins and content plugins, the error fires on every page, including the Joomla administrator dashboard. The site becomes completely unusable.

Similarly, the missing defaults/users/social.params.json generates continuous PHP warnings on every request:

PHP Warning: file_get_contents(.../defaults/users/social.params.json): Failed to open stream: No such file or directory in .../includes/user/user.php on line 5356

Expected behavior:

  1. If site.json is missing or contains invalid JSON, EasySocial should fall back to a bundled default configuration rather than throwing a fatal error that takes down the entire site.
  2. The error should be contained to EasySocial's own component pages, not propagated to the entire Joomla site.
  3. If a critical file is missing, EasySocial should display a clear admin notice ("EasySocial configuration file is missing — please reinstall or restore from backup") rather than a cryptic JSON parse error.
Steps to Reproduce
  1. Have a running Joomla 6.1.2 site with EasySocial (previous version) installed.
  2. Upload and install com_easysocial_BGv5.1.4_joomla.zip via Joomla Extensions → Install → Upload Package File.
  3. The EasySocial installer opens and begins "Extracting Files."
  4. If the server's PHP execution time or network conditions cause this step to take longer than the configured timeout, the browser request fails.
  5. On retry, "Extracting Files" fails because the ZIP has been deleted (Issue 1).
  6. If the extract succeeds, "Copying Files" stalls due to the volume of files in a single request (Issue 2).
  7. After a failed or timed-out installation, the entire Joomla site (frontend and backend) becomes inaccessible due to the missing site.json (Issue 3).
Recovery Steps Performed

For reference, recovering from this situation required the following manual SSH intervention:

  1. Locating and validating site.json from the installer's temp directory.
  2. Manually copying site.json and social.params.json to their correct locations.
  3. Re-extracting the inner component ZIP (com_easysocial_BGv5.1.4_pro.zip) and manually extracting each sub-package (admin.zip, site.zip, media.zip, plugins.zip, modules.zip, etc.) to their correct Joomla directories.
  4. Re-placing the deleted source ZIP back into setup/packages/.
  5. Patching 20+ installer controller files (installation.extract.php, installation.copy.php, installation.apps.php, installation.fields.php, etc.) to return immediate success responses, since the files were already in place.
  6. Restarting PHP-FPM to clear the opcode cache.
  7. Running the installer again with all controllers patched so the remaining database and configuration steps could complete.
  8. Restoring all patched controller files from backups after successful installation.

Total downtime: approximately 90 minutes.

Recommendations
  1. Do not delete the source ZIP until the full installation is confirmed complete.
  2. Implement batched file copying with AJAX chunking, consistent with how "Installing Applications" already works.
  3. Add a fallback mechanism for missing or corrupt site.json — load defaults rather than crashing.
  4. Scope EasySocial errors so they do not propagate beyond the component's own pages.
  5. Add a "repair installation" option in the admin backend that can re-extract and re-copy files from a still-present ZIP without requiring SSH access.
Environment Details
  • Server OS: Ubuntu 24.04.4 LTS
  • Server Panel: Plesk
  • Web Server: Apache with PHP-FPM
  • PHP: 8.5.9 (Plesk-managed)
  • PHP Settings at time of install:
    • max_execution_time: 600
    • memory_limit: 512M
    • post_max_size: 200M
    • upload_max_filesize: 200M
  • Disk space: 1.7 TB free
  • No other extensions were being installed simultaneously.

I am a long-time EasySocial customer and this is the first time an upgrade has caused this level of disruption. I would appreciate feedback on whether these issues are known and whether fixes are planned.

CreativeGraphics Support

Dear Markus

Thank you for your message and for your detailed analysis.

Be assured that we test all of our builds on different servers (dedicated and vps) and on different Joomla- and PHP-Versions before we release them.

Issue 1
We can confirm that exactly as described, installation.extract.php line 60: @File::delete($storage); runs unconditionally right after extraction. No subsequent step has completed yet at that point.

Issue 2
It's not true that there's "no batching at all" — installation.copy.php is invoked once per sub-package (admin, site, media, languages, etc.) as separate requests, so there is batching at that granularity.

Issue 3
config.php lines 89–96: if defaults/site.json is missing, file_get_contents() returns false, json_decode() returns null, and the code throws Exception('Invalid json syntax in site.json') — No fallback to bundled defaults anywhere in that path.

This case is a textbook timeout-window bug: it only bites when extraction+copy of a single sub-package genuinely exceeds the PHP execution window on that specific server (slower disk I/O, PHP-FPM worker limits, whatever).

We will make the installer more stable and fix these issues.

I put this ticket "on hold".

Best regards, Pascal

CreativeGraphics Support

Next time, please open a ticket immediately or call me directly on +41 79 400 72 29. I'll be happy to help.

CreativeGraphics Support

Dear Markus

Thank you again for having informed us in detail about the issues you encountered today.

We strive hard to give you the best and most stable experience possible.
Nevertheless parts of the original code are still old and it takes a lot of time to optimize and adapt, to always spot the problematic code snippets and in the meantime to develop further without breaking backwards compatibility.

As we appreciate your honest feedback and try to hold our promises, I sacrificed most of today to adapt and optimize the code for the CRE8 Social installer.

What we addressed:

Problem 1: ZIP deletion
`setup/controllers/installation.extract.php` deleted the just-uploaded/downloaded package ZIP immediately after extracting it — before any of its contents had actually been copied into place or verified. If a later install step failed, you were "left with a half-installed site" and no way to retry without re-downloading.

The Fix
We moved ZIP deletion to `setup/controllers/installation.post.php`, at the true end of `execute()`, only after every prior step has already reported success. 

Problem 2: Batched, resumable file copying
`setup/controllers/installation.copy.php` copied each package type (admin/site/media) as one single, unbatched, unresumable operation via `Folder::copy()`. On a large install or a slow/resource-limited host, this could exceed PHP's execution time limit or the browser's AJAX timeout mid-copy, leaving the install partially applied with no way to resume — it had to restart.

The Fix
Rewritten around a manifest-based batching system:
- On the first request for a type (`offset === 0`), the archive is extracted, the target directory tree is pre-created (including empty directories, which a per-file loop would otherwise silently drop), and a flat manifest of every file to copy is built and cached to disk (`{type}.manifest.json`).
- Each subsequent request resumes from the given `offset`, copying up to `BATCH_FILE_LIMIT` 300 files or until `BATCH_TIME_LIMIT` (20s — comfortably under the client's 60s AJAX timeout) is reached, then returns its new offset for the client to continue from.
- `cron.php`/`crondata.php` are preserved if already present at the target (never overwritten by a reinstall/update).
- The Languages step remains a single-shot copy (small, fixed file count — no batching needed).

Problem 3: Config-file-missing fallback
`admin/includes/config/config.php` threw a hard `Exception('Invalid json syntax in site.json')` if the config file was missing or unreadable at a point in the install, where no meaningful config should be expected to exist yet, converting a normal first-run state into a fatal error.

The Fix
Falls back to safe, empty default config data instead of throwing — `SocialRegistry`'s own `->get($key, $default)` already returns defaults for any missing key, so a genuinely empty starting config is a normal, harmless state rather than an error condition.

Problem 4: Joomla 6 Filesystem compatibility
The installer used still some instances of `Joomla\CMS\Filesystem\File`, but on Joomla 6.1+ without the core "Backward Compatibility" plugin active, `Joomla\CMS\Filesystem\File` does not reliably resolve — while the installer's own bundled compatibility autoloader (`setup/assets/compat/`) can supply `Folder` reliably, `File` specifically proved unreliable even with it available.

The Fix
Applied consistently across the entire `setup/controllers/` tree (9+ files) and `setup/bootstrap.php`:
- Every `File::exists/delete/write/copy/read` call converted to native PHP (`is_file`, `unlink`, `file_put_contents`, `copy`, `file_get_contents`), and the `use Joomla\CMS\Filesystem\File;` import removed everywhere it's no longer used.
- Every `Folder::files/folders/delete/create/exists/move/copy` call left untouched — these resolve reliably via the existing bundled compat autoloader, so converting them would have been unnecessary scope creep.
- One new helper added to the base `EasySocialSetupController` class, `makeDir($path, $mode = 0755)`, replicating Joomla's own `Folder::create()` umask-reset behavior (`umask(0)` before `mkdir()`, restored after, plus explicit `chmod()`) since a plain `mkdir()` doesn't guarantee the same permissions on a restrictive-umask host.

Verification
- Every changed file checked thoroughly and multiple times before being considered done.
- The batched copy flow, ZIP-deletion timing, and SEF-cache fix were each retested live on 3 hosts and confirmed working (PHP 8.3+ Joomla 5.4.8/PHP 8.4+ Joomla 6.1.3 and PHP 8.5+ Joomla 6.1.3).

Please find the adapted installer in version 5.1.4 of CRE8 Social. Just download the component again and reinstall it.

Please always do a backup before installation.

Have a nice evening.

Best regards, Pascal

markusberwing

Hi Pascal,

Thank you so much for the incredibly fast turnaround — I genuinely appreciate that you dedicated most of your day to addressing the issues I reported. The fixes for the ZIP deletion timing, the batched file copying, the config fallback, and the Joomla 6 Filesystem compatibility are exactly right, and the detail in your changelog shows real care for the product.

I immediately tested the updated v5.1.4 installer on my second EasySocial site (chaos.fashion, same server — Ubuntu 24.04, Plesk, PHP 8.5.9, Joomla 6.1.2). Here's what I found:

What Works Now

The three core fixes you made are working perfectly:

  1. Extracting Files — completed successfully, and the ZIP is no longer deleted prematurely. When I needed to retry, the ZIP was still in place. Excellent.
  2. Copying Files — the new manifest-based batching system works flawlessly. The step completed without stalling or timing out. This was the single biggest improvement.
  3. Config fallback — I did not encounter the "Invalid json syntax in site.json" fatal error at any point during the installation. The fallback is working as intended.
Remaining Problem: Same Timeout Issue in Other Installation Steps

Unfortunately, several of the subsequent installation steps suffer from the same single-request, no-batching, no-resume problem that the old installation.copy.php had before your fix. Specifically:

installation.fields.php — "Installing Custom Fields"

This step stalled completely and never returned a response. PHP-FPM showed 0% CPU after a few seconds — the request had died silently. Clicking "Retry" restarted the step from scratch, and it stalled again in the same way.

Looking at the code, the cause is identical to the old copy controller: it extracts {group}fields.zip and copies all field plugins into media/com_easysocial/apps/fields/{group}/ in a single request, with no batching, no offset tracking, and no resume capability.

installation.badges.php, installation.profiles.php, installation.reactions.php, and others — "Initializing Core Items" and subsequent steps

These also stalled in the same pattern: the AJAX request fires, PHP works briefly, then goes idle, and the browser shows the loading indicator indefinitely. Retry does not help.

How I Completed the Installation

To get through the installation, I had to apply the same workaround as before: temporarily patching each stalled controller to return an immediate success response, since the files had already been extracted and copied into place by the earlier (now working) steps. After the installer completed all steps, I restored the original controller files from backups.

The controllers I had to patch to bypass were:

  • installation.fields.php
  • installation.access.php
  • installation.adminmodules.php
  • installation.alerts.php
  • installation.badges.php
  • installation.categories.php
  • installation.download.php
  • installation.emoticons.php
  • installation.post.php
  • installation.privacy.php
  • installation.profiles.php
  • installation.reactions.php
  • installation.sql.php
  • installation.sync.php
  • installation.toolbar.php
  • installation.workflows.php

After patching all of these, the installer completed successfully and CRE8 Social is running correctly on both sites.

Suggestion

The manifest-based batching system you built for installation.copy.php is the right pattern. These remaining controllers would benefit from the same approach — or at least from a simpler version of it:

  1. Extract the archive once on the first request (offset 0).
  2. Build a file list / item list and cache it.
  3. Process N items per request and return the new offset.
  4. Let the client loop until all items are processed.

This is exactly what installation.copy.php now does, and it works perfectly there. The "Installing Applications" step also already works this way (it processes apps in groups via multiple AJAX calls), which is why that step completes reliably.

Alternatively, for the simpler steps (badges, reactions, emoticons, profiles) that only write a handful of database records, the issue might simply be that the archive extraction within the step is what takes too long — in which case, skipping the extraction entirely (since installation.copy.php has already placed all files) and only running the database/registration logic would solve it without needing full batching.

Environment (unchanged from previous report)
  • Server OS: Ubuntu 24.04.4 LTS
  • Server Panel: Plesk
  • Web Server: Apache with PHP-FPM
  • PHP: 8.5.9
  • PHP Settings: max_execution_time: 600, memory_limit: 512M
  • Disk space: 1.7 TB free
  • Tested on: chaos.fashion (Joomla 6.1.2)

Thank you again for the quick and thorough response to the first report. The three core fixes are solid and have already saved me significant trouble on this second installation. I hope this follow-up helps you extend the same reliability to the remaining installer steps.

Best regards, Markus

CreativeGraphics Support

Dear Markus

Thank you very much for your feedback.

Honestly, I am stunned that such a "mighty" server stalls at the installation.fields.php step with ~40 field types and subsequently also on the small badges like the privacy (zip of 5KB) or on badges (6KB).
Means that installUserFields installation takes well over 60 seconds. 

Then the browser gives up, jQuery aborts the request and shows the Retry button.
But aborting the XHR only closes the browser's end of the connection, PHP-FPM doesn't stop...

To grant maximum compatibility I have written a two-parts fix for the remaining files (extended the proven logic). 

Fix 1: session_write_close() once each step has read what it needs so that a slow fields step can no longer freeze subsequent batches.  
Fix 2: rewrote installation.fields.php to the exact installation.copy.php pattern

No request now exceeds ~20s and the 60s timeout is never hit.

The fixed installer will be released in the next build I'm currently developing, version 5.1.5 (will be released, soon).

I put this ticket "on hold" until the changed installer has been tested and finishes successfully on your server.

Thank you very much for reporting.

Best regards, Pascal

PS: Would it be possible to get a temporary access to exactly that server? So I could test on that infrastructure directly.

CreativeGraphics Support

Dear Markus

I implemented the described fixes in version 5.1.5 of the component-installer.

Everything is now batched and the session is kept active throughout the whole process.

The installer comes with a one-time executing script to alias all the countries-states-region-names. Also this script should run through smoothly, but it takes some time to finish as it inserts a lot of rows into the db. 

Please let me know how it goes and if everything finishes now in "one go", as intended.

I tested the installer various times on different servers with PHP 8.3/8.4 and 8.5 and it never failed.

I hope to have been able to solve the issues you encountered with that revised installer.

Have a nice evening.

Best regards, Pascal

markusberwing

Hi Pascal,

Thank you for the v5.1.5 fixes — the batched installation.copy.php and the session_write_close() changes are working perfectly.

Unfortunately, the installer still stalls on my server at "Installing Custom Fields" and all subsequent steps.

Here is a full diagnostic instead of server access, which should give you everything you need.

What Happens
  1. "Extracting Files" through "Installing Applications" complete successfully.
  2. "Installing Custom Fields" stalls — the browser shows the loading indicator indefinitely.
  3. Clicking "Retry" fires new requests, which return HTTP 200, but the step never completes.
  4. The same happens for all subsequent steps if I patch past "Installing Custom Fields."

I had to patch every remaining controller to return {state: true, done: true, offset: 0, total: 0} to complete the installation. Note: my initial patches returned {state: true, complete: true} which caused the client to loop endlessly — the client checks result.done, not result.complete.

Root Cause: jQuery AJAX Timeout

Confirmed in your installer source:

setup/assets/scripts/script.js: timeout: 60000, // 60 second timeout

Your installation.fields.php v5.1.5 uses BATCH_TIME_LIMIT = 15 and BATCH_ITEM_LIMIT = 10, which should keep each batch well under 60 seconds. However, the first request (offset=0) does three things before the batch loop even starts:

  1. Extracts the archive (extractArchive)
  2. Creates the target directory
  3. Builds the manifest (reads all folders, writes JSON)
  4. Calls $this->engine() to bootstrap EasySocial
  5. Then starts the first batch of 10 installField() calls

If steps 1–4 plus the first batch collectively exceed 60 seconds, the jQuery timeout fires, the XHR is aborted, and the "Retry" button appears. PHP-FPM keeps running (there is no request_terminate_timeout set), but the browser has already given up.

The Other Controllers Are Not Batched

The following controllers still use the old single-request pattern — no offset, no batching, no time limit. They all stall on my server:

  • installation.badges.php
  • installation.profiles.php
  • installation.reactions.php
  • installation.emoticons.php
  • installation.privacy.php
  • installation.categories.php
  • installation.alerts.php
  • installation.access.php
  • installation.adminmodules.php
  • installation.download.php
  • installation.post.php
  • installation.sql.php
  • installation.sync.php
  • installation.toolbar.php
  • installation.workflows.php

Each of these needs the same done/offset/total batching treatment that installation.copy.php and installation.fields.php now have — or at minimum, should skip archive extraction when the files are already in place (since installation.copy.php has already copied everything).

Suggested Fix for installation.fields.php

Split the first request's work: offset=0 should ONLY extract + build manifest + return. The actual installField() calls should start at offset=1 (or offset=0 on the second request). This guarantees the extraction overhead never compounds with the batch work.

Server Diagnostics

CPU: AMD EPYC 4344P 8-Core (16 threads, 3.8 GHz base, 5.4 GHz boost)

Disk I/O: 995 MB/s sequential write RAM: ~18% of total used MySQL: MariaDB 10.11.14

EasySocial: 147 tables, largest 8 MB (social_stream)

PHP: 8.5.10 via Plesk PHP-FPM max_execution_time: 600 memory_limit: 512M request_terminate_timeout: not set (unlimited) pm: ondemand pm.max_children: 10 pm.process_idle_timeout: 10s Apache TimeOut: 600 Nginx proxy_read_timeout: 600 jQuery AJAX timeout: 60000ms (script.js line confirmed)

The server is not resource-constrained — this is a dedicated EPYC with 1.8 TB SSD and 16 threads. The bottleneck is purely the 60-second client-side timeout versus installation steps that exceed it.

What I Need

Either:

Option A: Apply the copy.php-style batching to all remaining installation controllers, with the extraction separated from the first batch.

Option B: Increase the jQuery AJAX timeout in script.js to 300000 (5 minutes) to match the server-side timeouts. This is the simpler fix, though batching is more robust long-term.

Option C: Make the remaining controllers skip their own archive extraction entirely when the target files already exist (since installation.copy.php has already placed them), and only run the database/registration logic.

I'm happy to test any updated build immediately on both of my sites (same server, same config).

Best regards, Markus

CreativeGraphics Support

Dear Markus

Thank you very much for letting me know about that. I never saw a server with such good and powerful hardware timeout on relatively small badges (1-4). I am honestly stunned that this takes more than 60s to complete. On all of our testhosts, we're nowhere near this timeout.

Nevertheless, we will make the installer even more robust. Be assured that we do everything to make it work for you as smoothly and flawless as possible. 

As I departed for a 2-weeks holiday this morning, I will put this ticket "on hold", as the issue obviously persists. I will strenghten and optimize the installer as soon as i return from my journey.

Take care and have a good time! 

Thank you very much for reporting.

Best regards, Pascal

We use cookies
We use cookies on our website. Some of them are essential for the operation of the site, while others help us to improve this site and the user experience. You can decide whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.