diff --git a/zerver/lib/exceptions.py b/zerver/lib/exceptions.py index e9e04f2bc1..45d4189522 100644 --- a/zerver/lib/exceptions.py +++ b/zerver/lib/exceptions.py @@ -190,6 +190,18 @@ class StreamWithIDDoesNotExistError(JsonableError): return _("Channel with ID '{stream_id}' does not exist") +class IncompatibleParametersError(JsonableError): + data_fields = ["parameters"] + + def __init__(self, parameters: List[str]) -> None: + self.parameters = ", ".join(parameters) + + @staticmethod + @override + def msg_format() -> str: + return _("Unsupported parameter combination: {parameters}") + + class CannotDeactivateLastUserError(JsonableError): code = ErrorCode.CANNOT_DEACTIVATE_LAST_USER data_fields = ["is_last_owner", "entity"] diff --git a/zerver/lib/streams.py b/zerver/lib/streams.py index f6801e406a..6857651105 100644 --- a/zerver/lib/streams.py +++ b/zerver/lib/streams.py @@ -7,6 +7,7 @@ from django.utils.translation import gettext as _ from zerver.lib.default_streams import get_default_stream_ids_for_realm from zerver.lib.exceptions import ( + IncompatibleParametersError, JsonableError, OrganizationAdministratorRequiredError, OrganizationOwnerRequiredError, @@ -326,7 +327,7 @@ def check_for_exactly_one_stream_arg(stream_id: Optional[int], stream: Optional[ raise JsonableError(error) if stream_id is not None and stream is not None: - raise JsonableError(_("Please supply only one channel parameter: name or ID.")) + raise IncompatibleParametersError(["stream_id", "stream"]) def check_stream_access_for_delete_or_update( diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml index a068105857..b5bf537a55 100644 --- a/zerver/openapi/zulip.yaml +++ b/zerver/openapi/zulip.yaml @@ -18862,6 +18862,7 @@ paths: oneOf: - $ref: "#/components/schemas/InvalidApiKeyError" - $ref: "#/components/schemas/MissingArgumentError" + - $ref: "#/components/schemas/IncompatibleParametersError" - $ref: "#/components/schemas/UserNotAuthorizedError" "401": description: | @@ -21395,6 +21396,31 @@ components: "result": "error", "var_name": "content", } + IncompatibleParametersError: + allOf: + - $ref: "#/components/schemas/CodedErrorBase" + - additionalProperties: false + description: | + ## Incompatible request parameters + + A typical failed JSON response for when two or more, optional + parameters are supplied that are incompatible with each other. + properties: + result: {} + msg: {} + code: {} + parameters: + type: string + description: | + A string containing the parameters, separated by commas, + that are incompatible. + example: + { + "code": "BAD_REQUEST", + "msg": "Unsupported parameter combination: object_id, object_name", + "result": "error", + "parameters": "object_id, object_name", + } UserNotAuthorizedError: allOf: - $ref: "#/components/schemas/CodedError" diff --git a/zerver/tests/test_user_topics.py b/zerver/tests/test_user_topics.py index 08f3144f42..e8a8114f2d 100644 --- a/zerver/tests/test_user_topics.py +++ b/zerver/tests/test_user_topics.py @@ -198,7 +198,7 @@ class MutedTopicsTestsDeprecated(ZulipTestCase): data = {"stream": stream.name, "stream_id": stream.id, "topic": "Verona3", "op": "add"} result = self.api_patch(user, url, data) - self.assert_json_error(result, "Please supply only one channel parameter: name or ID.") + self.assert_json_error(result, "Unsupported parameter combination: stream_id, stream") data = {"stream_id": stream.id, "topic": "a" * (MAX_TOPIC_NAME_LENGTH + 1), "op": "add"} result = self.api_patch(user, url, data) @@ -238,7 +238,7 @@ class MutedTopicsTestsDeprecated(ZulipTestCase): data = {"stream": stream.name, "stream_id": stream.id, "topic": "Verona3", "op": "remove"} result = self.api_patch(user, url, data) - self.assert_json_error(result, "Please supply only one channel parameter: name or ID.") + self.assert_json_error(result, "Unsupported parameter combination: stream_id, stream") data = {"stream_id": stream.id, "topic": "a" * (MAX_TOPIC_NAME_LENGTH + 1), "op": "remove"} result = self.api_patch(user, url, data)