Page MenuHomePhabricator

Edit API with appendtext & a contentmodel change gives an internal api error
Open, LowPublicBUG REPORT

Description

List of steps to reproduce (step by step, including full links if applicable):

  1. Make a page called User:RheingoldRiver/Test (or whatever sandbox page)
  2. Give it contentmodel text.

Then this API query (I ran them in the API sandbox so it's definitely not a connection/library issue) gives an internal MediaWiki error (see below):

{
	"action": "edit",
	"format": "json",
	"title": "User:RheingoldRiver/Test",
	"appendtext": "asdf",
	"contentmodel": "wikitext",
	"token": (token here)
}

But this one (with text) will go through:

{
	"action": "edit",
	"format": "json",
	"title": "User:RheingoldRiver/Test",
	"text": "asdf",
	"contentmodel": "wikitext",
	"token": (token here)
}

What happens?:

I get this error message:

{
    "error": {
        "code": "internal_api_error_MWException",
        "info": "[436f0277b9c349e2] Caught exception of type MWException",
        "errorclass": "MWException"
    }
}

What should have happened instead?:

It should append the text & change the contentmodel to wikitext.

Software version (if not a Wikimedia wiki), browser information, screenshots, other information, etc:

Event Timeline

Majavah added a subscriber: Majavah.

Reproduced with 1.37.0-wmf.1 as well (testwiki). Stack trace:

[2d72cb73-7387-47f6-a8ed-526a581ae73b] Exception caught: Format text/x-wiki is not supported for content model text
MWException at /srv/mediawiki/php-1.37.0-wmf.1/includes/content/ContentHandler.php(546)
from /srv/mediawiki/php-1.37.0-wmf.1/includes/content/ContentHandler.php(546)
#0 /srv/mediawiki/php-1.37.0-wmf.1/includes/content/TextContentHandler.php(46): ContentHandler->checkFormat(string)
#1 /srv/mediawiki/php-1.37.0-wmf.1/includes/content/AbstractContent.php(170): TextContentHandler->serializeContent(TextContent, string)
#2 /srv/mediawiki/php-1.37.0-wmf.1/includes/api/ApiEditPage.php(215): AbstractContent->serialize(string)\n#3 /srv/mediawiki/php-1.37.0-wmf.1/includes/api/ApiMain.php(1652): ApiEditPage->execute()
#4 /srv/mediawiki/php-1.37.0-wmf.1/includes/api/ApiMain.php(622): ApiMain->executeAction()
#5 /srv/mediawiki/php-1.37.0-wmf.1/includes/api/ApiMain.php(593): ApiMain->executeActionWithErrorHandling()
#6 /srv/mediawiki/php-1.37.0-wmf.1/api.php(90): ApiMain->execute()
#7 /srv/mediawiki/php-1.37.0-wmf.1/api.php(45): wfApiMain()
#8 /srv/mediawiki/w/api.php(3): require(string)
#9 {main}
Reedy updated the task description. (Show Details)
Reedy added a subscriber: Reedy.

What should have happened instead?:
It should append the text & change the contentmodel to wikitext.

I think the bare minimum is it shouldn't fail with an unhandled error like that.

How it should handle mixed content models is a different issue. It seems reasonable enough that MW rejects the addition of text in a different content model during the "edit" of an existing page.

The help text doesn't say it will change the content model, just that you're identifying what content model it's in (which is probably more useful on page creation than anything else)

contentmodel:    Content model of the new content. 
    One of the following values: GadgetDefinition, JsonSchema, MassMessageListContent, Scribunto, SecurePoll, css, javascript, json, sanitized-css, text, unknown, wikitext

So a Documentation update might be beneficial there too

I think it should allow both changes because it's possible for a script to encounter a page that was initialized with the wrong contentmodel, then want to append text to it & fix the contentmodel.

My use case is that I've created a backup namespace (which should just be default plaintext, but I don't have access to change that parameter currently, so I'm setting it in my code) where I'm backing up versions of templates from the live wiki and saving them, along with a lookup key, so I can retrieve later; this way, if performing a particularly complex automated / impactful edit, I don't have to deal with revision history to find the original version of the code if I have to restore. But someone could create a backup on the wiki with wrong content model (i.e. just use default wikitext), and I'd want to just append to this & change contentmodel to plaintext.

Also, currently you can't even change the contentmodel without recreating the page entirely, since one of text, appendtext, prependtext, or undo is required. So if the process to append + change contentmodel becomes two api calls, then contentmodel should be allowed as another option for provided parameter.

Also, currently you can't even change the contentmodel without recreating the page entirely, since one of text, appendtext, prependtext, or undo is required. So if the process to append + change contentmodel becomes two api calls, then contentmodel should be allowed as another option for provided parameter.

Not correct.

Special:ChangeContentModel and https://en.wikipedia.org/w/api.php?action=help&modules=changecontentmodel

As per the PHP docs for the class

* Api module to change the content model of existing pages
*
* For new pages, use the edit api and specify the desired content model and format.

Ah, I didn't realize changecontentmodel existed since we're on 1.33 still, sorry.

So like I say, the failure needs handling better, for sure, maybe some documentation improvements surrounding it...

But using action=edit to handle content model changes might not happen, and I guess it's less likely Fandom would backport it to their version of 1.33

So like I say, the failure needs handling better, for sure, maybe some documentation improvements surrounding it...

But using action=edit to handle content model changes might not happen, and I guess it's less likely Fandom would backport it to their version of 1.33

Using action=edit is appropriate for content model changes that need to be done as part of an edit (example: T267461#6610371 - couldn't edit without changing content model, and couldn't change content model without editing)

Specifically, action=edit with a content model specified tries to change the content model during an edit, while action=changecontentmodel *just* changes the content model without an extra edit, and I added that api module to match how Special:ChangeContentModel can be used without an extra edit

afaik the plan is for us to start updating regularly - we're not on forked MediaWiki anymore, but we are behind on versions for sure. I have no idea what the plan for updates is though, just that they're supposed to happen.

What I really want to avoid is having to make an extra api call on every single edit when I need to append text & enforce a contentmodel, and ideally also not have edits fail. So if I could set a contentmodel & add appendtext, and it makes the edit successfully, but warns me that my contentmodel doesn't match, I think that would be fine too; then I can make the 2nd api call only when necessary, and never more than 2 total. I would still definitely prefer for the contentmodel change to happen with the one call but I can see the justification for not allowing it.

ApiEditPage.php
			// @todo Add support for appending/prepending to the Content interface

			if ( !( $content instanceof TextContent ) ) {
				$this->dieWithError( [ 'apierror-appendnotsupported', $contentModel ] );
			}

There is a contentmodel and a contentformat

There is no check if the existing page supports the given model and format, which is needed for the append/prepend, because it is interacting with the current content of the page.