Skip to content

Cron crashes when post format maximum length is non-numeric #1108

Description

@pirate-bot

Summary

Scheduled sharing can terminate with TypeError: Unsupported operand types: string - int when formatting a post.

Expected behavior: a saved post format supplies a usable content-length value and scheduled sharing proceeds.

Actual behavior: a non-numeric saved maximum-length value reaches content-length arithmetic and crashes the cron request.

Impact: affected scheduled shares are not processed while this error occurs.

Customer context

  • Product / area: Revive Social scheduled sharing and post-format content generation
  • Version: 9.4.1
  • Environment: WordPress 7.0.2; PHP 8.3.32; cron request
  • Integration / third party: Not applicable
  • Reported error / symptom: TypeError: Unsupported operand types: string - int
  • Impact: 23 telemetry occurrences across one distinct site during the query window.

Reproduction notes

  1. Configure an account with a post format whose persisted maximum_length is a non-numeric string.
  2. Queue a post for that account and allow its scheduled cron event to run.
  3. The reported path reaches post-content formatting and production telemetry shows TypeError: Unsupported operand types: string - int.

Reproduction is source-confirmed from the production stack and tagged code; the original saved value is unavailable.

Diagnosis

Conclusion

Production telemetry identifies Rop_Post_Format_Helper::build_content() at the reported source location during cron processing. In tagged v9.4.1, maximum_length is read from persisted post-format data without normalization and then used as the left operand in string-minus-integer arithmetic. The REST and model save paths permit non-numeric strings to be stored, making the reported PHP 8.3 TypeError a confirmed product defect.

Where this likely occurs

  • includes/admin/helpers/class-rop-post-format-helper.phpRop_Post_Format_Helper::build_content() lines 147-153 reads $this->post_format['maximum_length'] directly; lines 253-265 calculates $max_length - ... - $custom_length, with line 257 matching telemetry.
  • includes/admin/class-rop-rest-api.phpRop_Rest_Api::save_post_format() lines 371-390 only caps Twitter values after an integer comparison; non-numeric strings are not normalized and non-Twitter formats have no equivalent validation.
  • includes/admin/models/class-rop-post-format-model.phpRop_Post_Format_Model::add_update_post_format() approx. lines 114-118 persists supplied format data through the generic model storage path without field type enforcement.
  • includes/admin/models/class-rop-queue-model.phpRop_Queue_Model::prepare_post_object() lines 431-436 invokes get_formated_object(); includes/admin/class-rop-admin.phpRop_Admin::rop_cron_job() lines 1218-1243 reaches that method for due queued posts.
  • v9.4.1 points at 752e0ee6c324c134b8c8ddd85818b760654f8d08. git blame attributes the subtraction at line 257 to 371c0ad86; the expression remains in the release tag.

Engineering notes

  • Default post-format values intentionally represent maximum_length as numeric strings, such as Twitter's '240', in includes/admin/class-rop-global-settings.phpRop_Global_Settings::$post_format_defaults approx. lines 205-449. Numeric strings coerce in the observed expression; the failure evidence is consistent with a non-numeric persisted string.
  • The Vue editor presents maximum_length as a number input, but the request path sends the complete format data and does not provide a server-side schema boundary: vue/src/vue-elements/accounts-selector-panel.vue approx. lines 248-263 and includes/admin/class-rop-rest-api.php lines 94-101.
  • Legacy migration also copies the previous length option into the post format without type normalization: includes/admin/helpers/class-rop-db-upgrade.phpRop_DB_Upgrade::migrate_post_formats() approx. lines 228-293.
  • get_custom_length() derives an integer from a scalar custom_text value at includes/admin/helpers/class-rop-post-format-helper.phpRop_Post_Format_Helper::get_custom_length() lines 414-435. The inspected telemetry and source location point to maximum_length as the string operand in the reported arithmetic error.

Test coverage status

  • tests/test-post-format.phpTest_RopPostFormat::test_post_format() lines 189-220 asserts a default string maximum length and saves an integer value, but does not format a post with invalid persisted length data.
  • tests/test-x-premium-limit.php covers the Twitter upper-bound behavior, but its assertions cast saved values to integers and do not exercise non-numeric values during scheduled formatting.
  • No relevant coverage was found during inspection for a non-numeric persisted maximum_length reaching build_content() in the cron queue path.

What to verify or explore next

  • Reproduce scheduled formatting with a post format whose persisted maximum_length is a non-numeric string, on the supported PHP 8.3 environment.
  • Check whether post formats migrated from legacy options or saved through the REST route can contain non-numeric length values in affected installations.
  • Run the post-format and queue PHPUnit suites after adding coverage for the reported input and cron path.

Unknowns / follow-up

  • Telemetry does not contain the persisted post-format payload, so the exact non-numeric value and entry route are unknown.
  • The available evidence covers the free plugin repository; no Pro override of this arithmetic path was found during inspection.

Confidence

Confidence: 97/100

Production telemetry records 23 cron crashes on one site running v9.4.1/PHP 8.3.32, and the tagged source lets a persisted non-numeric maximum_length reach the exact failing string-minus-integer expression without type validation.

Crash telemetry

Occurrences 23
Distinct sites 1
First seen 2026-08-04 17:01 UTC
Last seen 2026-08-05 04:03 UTC
Crash location product:includes/admin/helpers/class-rop-post-format-helper.php:257
Request context cron
Inside Themeisle SDK no
Product versions 9.4.1
WP versions 7.0.2
PHP versions 8.3.32
SDK versions 3.3.58

Source: automated crash report — tweet-old-post, fingerprint e32435e67e4238ba8337cad9df1fcd3a
Generated by bug-report-triage (ID: bug-report-triage_6a72d18106df89.42530208)

Metadata

Metadata

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions