Skip to content

Error when running fl2 upgrade 2.0 on my extension #51

Description

@huoxin233

Managed to fix it via huoxin233/flarum-ext-money-with-history@b2654a8, not sure if the issue in cli is valid and still worth fixing


I ran fl2 upgrade 2.0 on my Money with History extension huoxin233/flarum-ext-money-with-history@e49634e

Got an error half way through:

  STEP 12/16    Prepare for JSON:API changes.

     =>     DONE     Flarum 2.0 completely refactors the JSON:API implementation. The way resource CRUD operations,
                     serialization and extending other resources is done has completely changed.

                     The tool cannot completely automate this change, but it has added some boilerplate code and TODO comments to help you get started.
                     You should make whatever changes you can now, then properly test and adapt your code once the upgrade process is over.

                     Read more: https://docs.flarum.org/2.x/extend/update-2_0#jsonapi

                     Checkout our additional guide which provides concrete examples for the upgrading process of the JSON:API layer:
                     https://docs.flarum.org/2.x/extend/update-2_0-api

     =>    COMMIT    chore(2.0): JSON:API changes

  STEP 13/16    Intervention Image Library v3

     =>   WORKING.  
Error occurred, and could not complete:
The PHP subsystem returned an invalid value: Syntax error, unexpected '{' on line 15 - #0 /home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php(185): PhpParser\ParserAbstract->doParse()
#1 /home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/php-subsystem/src/Upgrade/Replacement.php(29): PhpParser\ParserAbstract->parse()
#2 /home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/php-subsystem/index.php(37): Flarum\CliPhpSubsystem\Upgrade\Replacement->handle()
#3 {main}
Error: The PHP subsystem returned an invalid value: Syntax error, unexpected '{' on line 15 - #0 /home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php(185): PhpParser\ParserAbstract->doParse()
#1 /home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/php-subsystem/src/Upgrade/Replacement.php(29): PhpParser\ParserAbstract->parse()
#2 /home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/php-subsystem/index.php(37): Flarum\CliPhpSubsystem\Upgrade\Replacement->handle()
#3 {main}
    at PhpSubsystemProvider.handlePhpError (/home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/lib/providers/php-provider.js:48:19)
    at PhpSubsystemProvider.run (/home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/lib/providers/php-provider.js:34:14)
    at /home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/lib/steps/upgrade/twopointoh/backend/intervention-image.js:16:35
    at InterventionImage.applyReplacements (/home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/lib/steps/upgrade/twopointoh/base.js:164:34)
    at applyOn (/home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/lib/steps/upgrade/twopointoh/base.js:103:47)
    at async InterventionImage.run (/home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/lib/steps/upgrade/twopointoh/base.js:134:13)
    at async StepManager.runStep (/home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/lib/boilersmith/step-manager.js:179:23)
    at async checkAndRun (/home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/lib/boilersmith/step-manager.js:92:24)
    at async StepManager.run (/home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/lib/boilersmith/step-manager.js:113:21)
    at async TwoPointOh.run (/home/huoxin/.nvm/versions/node/v24.15.0/lib/node_modules/fl2/lib/base-command.js:71:21)

Before the error, the following steps were completed:

Saw that at Step 12 Prepare for JSON:API changes, a file src/Api/Resource/MoneyHistoryResource.php is created with syntax error, it is nothing behind the implements:

<?php

namespace Huoxin\MoneyWithHistory\Api\Resource;

use Flarum\Api\Context;
use Flarum\Api\Endpoint;
use Flarum\Api\Resource;
use Flarum\Api\Schema;
use Tobyz\JsonApiServer\Context as OriginalContext;

/**
 * @extends Resource\AbstractResource<object>
 */
class MoneyHistoryResource extends Resource\AbstractResource implements 
{
...

Review from AI: The Root Cause: A Misplaced Comma

When the Flarum 2.0 migration script (or a user running flarum-cli make api-resource) generates a new Api\Resource without an attached model class, the template logic mistakenly swallows the comma meant to separate the endpoints in the returned PHP array.

Take a look at the original EJS logic for the endpoints() array (lines 36-38):

        return [<% if (endpoints.includes('create')) { %>
            Endpoint\Create::make()<% if (modelClassName) { %>
                ->can('create<%= modelClassName %>'),<% } %><% } %><% if (endpoints.includes('update')) { %>
            Endpoint\Update::make()
                ->can('update'),

The trailing comma , for the Endpoint\Create::make() element was placed inside the <% if (modelClassName) { %> conditional block.

If the upgrade script encounters a scenario where it generates an API resource that is not tied to a Flarum Database Model (or if the AST parser failed to extract the model class cleanly from the legacy serializer), modelClassName evaluates to false. This results in the EJS generating the following malformed PHP output:

        return [
            Endpoint\Create::make()
            Endpoint\Update::make()
                ->can('update'),
        ];

Because Endpoint\Create::make() lacks a trailing comma, it immediately breaks the PHP array syntax. Flarum CLI uses nikic/php-parser under the hood to perform AST transformations. When the subsequent "Intervention Image Library" upgrade step kicks in, it attempts to parse all .php files in your src/ directory. The parser encounters this malformed array inside your newly generated MoneyHistoryResource.php and crashes the entire upgrade process with a syntax error.

Fix provided from AI

diff --git a/boilerplate/stubs/backend/advanced-api-resource.php b/boilerplate/stubs/backend/advanced-api-resource.php
index be6040d..b27d8b6 100644
--- a/boilerplate/stubs/backend/advanced-api-resource.php
+++ b/boilerplate/stubs/backend/advanced-api-resource.php
@@ -14,7 +14,7 @@ use Tobyz\JsonApiServer\Context as OriginalContext;
 /**
  * @extends <% if (modelClassName) { %>Resource\AbstractDatabaseResource<<%= modelClassName %>><% } else { %>Resource\AbstractResource<object><% } %>
  */
-class <%= className %> extends <% if (modelClassName) { %>Resource\AbstractDatabaseResource<% } else { %>Resource\AbstractResource<% if (interfaces.length > 0) %> implements <%= interfaces.join(', ') %><% } %>
+class <%= className %> extends <% if (modelClassName) { %>Resource\AbstractDatabaseResource<% } else { %>Resource\AbstractResource<% if (interfaces.length > 0) { %> implements <%= interfaces.join(', ') %><% } %><% } %>
 {
     public function type(): string
     {
@@ -35,13 +35,13 @@ class <%= className %> extends <% if (modelClassName) { %>Resource\AbstractDatab
     {
         return [<% if (endpoints.includes('create')) { %>
             Endpoint\Create::make()<% if (modelClassName) { %>
-                ->can('create<%= modelClassName %>'),<% } %><% } %><% if (endpoints.includes('update')) { %>
+                ->can('create<%= modelClassName %>')<% } %>,<% } %><% if (endpoints.includes('update')) { %>
             Endpoint\Update::make()
                 ->can('update'),<% } %><% if (endpoints.includes('delete')) { %>
             Endpoint\Delete::make()
                 ->can('delete'),<% } %><% if (endpoints.includes('show')) { %>
             Endpoint\Show::make()
-                ->authenticated(),<% } %><% if (endpoints.includes('list')) { %>
+                ->authenticated(),<% } %><% if (endpoints.includes('list') || endpoints.includes('index')) { %>
             Endpoint\Index::make()
                 ->paginate(),<% } %>
         ];
diff --git a/src/steps/stubs/backend/advanced-api-resource.ts b/src/steps/stubs/backend/advanced-api-resource.ts
index a539aec..9c12c49 100644
--- a/src/steps/stubs/backend/advanced-api-resource.ts
+++ b/src/steps/stubs/backend/advanced-api-resource.ts
@@ -72,6 +72,7 @@ export class GenerateAdvancedApiResourceStub extends BasePhpStubStep {
 
     const interfaceMap: Record<string, string> = {
       list: 'Resource\\Contracts\\Listable',
+      index: 'Resource\\Contracts\\Listable', // Add index as an alias for list
       show: 'Resource\\Contracts\\Findable',
       create: 'Resource\\Contracts\\Creatable',
       update: 'Resource\\Contracts\\Updatable',
@@ -79,7 +80,7 @@ export class GenerateAdvancedApiResourceStub extends BasePhpStubStep {
     };
 
     params.modelType ||= pluralKebabCaseModel(params.modelClassName as string);
-    params.interfaces = (params.endpoints as string[]).map((endpoint) => interfaceMap[endpoint]);
+    params.interfaces = (params.endpoints as string[]).map((endpoint) => interfaceMap[endpoint]).filter(Boolean);
 
     return params;
   }

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions