nextcloud / nextcloud/integration_mattermost
Sending files is broken: this.$set is not a function in SendFilesModal (leftover Vue 2 API after Vue 3 migration)
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 26
- Forks
- 10
- PR merge metrics
- No merged PRs in 30d
Description
How to use GitHub
- Please use the 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to show that you are affected by the same issue.
- Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
- Subscribe to receive notifications on status change and new comments.
Steps to reproduce
- Connect a Mattermost account under Settings → Connected accounts (personal access token).
- In the Files app, select a file and choose "Send to Mattermost".
- Pick a channel, leave the send type on file upload (not "public link" / "internal link"), then click the send button.
Expected behaviour
The file is uploaded to the selected channel and a message is posted.
Actual behaviour
Nothing happens. The modal stays in its loading state, no error is shown in the UI, and the file is never sent. Nothing is written to nextcloud.log, and the Mattermost server never receives a request — no POST /api/v4/files and no POST /api/v4/posts appear in its debug log.
The JavaScript console shows an uncaught TypeError (full log below).
Root cause
Vue.set / this.$set was removed in Vue 3. The app migrated to Vue 3 in 3.0.0 (#100), but two calls in src/components/SendFilesModal.vue were missed. They are the only two $set occurrences left in src/:
fileStarted(id) {
this.$set(this.fileStates, id, STATES.IN_PROGRESS) // line 409
},
fileFinished(id) {
this.$set(this.fileStates, id, STATES.FINISHED) // line 412
},
fileStarted() is called synchronously in src/filesplugin.js, before the upload request is issued:
OCA.Mattermost.MattermostSendModalVue.fileStarted(file.id) // line 266 — throws here
const url = generateUrl('apps/integration_mattermost/sendFile')
axios.post(url, req) // never reached
The TypeError aborts sendFileLoop() before axios.post() runs, which is why no request ever leaves the browser and no server-side log contains anything.
Suggested fix
In Vue 3 fileStates is a reactive proxy, so plain assignment is enough:
fileStarted(id) {
this.fileStates[id] = STATES.IN_PROGRESS
},
fileFinished(id) {
this.fileStates[id] = STATES.FINISHED
},
I applied the equivalent change to the shipped bundle (js/integration_mattermost-filesplugin.js) on a production instance and file sending works again, including the per-file progress indicator. Happy to open a PR.
Workaround for other affected users
Sending as a public or internal link still works — sendPublicLinks() and sendInternalLinks() never call fileStarted(). Only the direct file upload path is broken.
The affected code is unchanged on main at the time of writing.
Mattermost integration version: 3.2.0
Server configuration
Web server: Apache
Database: PostgreSQL
PHP version: 8.3.32
Nextcloud version: 33.0.6
Installation method: Nextcloud All-in-One (Docker)
List of activated apps
Enabled:
- admin_audit: 1.23.0
- admincockpit: 1.3.2
- appointments: 2.7.4
- arbeitszeitcheck: 1.5.9
- attendance: 1.41.2
- bruteforcesettings: 6.0.0
- calendar: 6.5.1
- call_summary_bot: 3.4.0
- circles: 33.0.0
- cloud_federation_api: 1.17.0
- comments: 1.23.0
- contacts: 8.7.4
- contactsinteraction: 1.14.1
- dashboard: 7.13.0
- dav: 1.36.0
- deck: 1.17.4
- external: 8.0.1
- federatedfilesharing: 1.23.0
- files: 2.5.0
- files_accesscontrol: 4.0.1
- files_confidential: 5.1.0
- files_downloadlimit: 5.1.0
- files_external: 1.25.1
- files_fulltextsearch: 33.0.0
- files_pdfviewer: 6.0.0
- files_reminders: 1.6.0
- files_sharing: 1.25.2
- files_trashbin: 1.23.0
- files_versions: 1.26.0
- firstrunwizard: 6.0.0
- fulltextsearch: 33.0.0
- fulltextsearch_elasticsearch: 33.0.0
- groupfolders: 21.0.10
- integration_documenso: 2.1.0
- integration_giphy: 2.2.1
- integration_matrix: 1.1.0
- integration_mattermost: 3.2.0
- integration_peertube: 2.1.1
- logreader: 6.0.0
- lookup_server_connector: 1.21.0
- mail: 5.10.8
- nextcloud-aio: 0.8.0
- nextcloud_announcements: 5.0.0
- notes: 6.0.1
- notifications: 6.0.0
- notify_push: 1.3.5
- oauth2: 1.21.0
- ownershiptransfer: 1.5.0
- password_policy: 5.0.0
- privacy: 5.0.0
- profile: 1.2.0
- provisioning_api: 1.23.0
- richdocuments: 10.3.0
- serverinfo: 5.0.0
- settings: 1.16.0
- sharebymail: 1.23.0
- spreed: 23.0.9
- support: 5.0.0
- systemtags: 1.23.0
- tables: 2.2.0
- talk_matterbridge: 1.34.1026000
- tasks: 0.18.1
- text: 7.0.1
- theming: 2.8.0
- twofactor_backupcodes: 1.22.0
- twofactor_nextcloud_notification: 7.0.0
- twofactor_totp: 15.0.0
- updatenotification: 1.23.0
- user_migration: 10.4.0
- user_status: 1.13.0
- viewer: 6.0.0
- webhook_listeners: 1.5.0
- workflowengine: 2.15.0
Disabled:
- activity: 6.0.0 (installed 5.0.0)
- app_api: 33.0.0 (installed 32.0.0)
- encryption: 2.21.0
- federation: 1.23.0 (installed 1.22.0)
- files_archive: 1.2.8 (installed 1.2.8)
- forms: 5.3.4 (installed 5.3.4)
- google_synchronization: 4.2.0 (installed 4.2.0)
- integration_google: 4.4.0 (installed 4.4.0)
- photos: 6.0.0 (installed 5.0.0)
- recommendations: 6.0.0 (installed 5.0.0)
- related_resources: 4.0.0 (installed 3.0.0)
- survey_client: 5.0.0 (installed 4.0.0)
- suspicious_login: 11.0.0
- timesheet: 1.2.0 (installed 1.2.0)
- user_ldap: 1.24.0
- weather_status: 1.13.0 (installed 1.12.0)
Nextcloud configuration
{
"system": {
"one-click-instance": true,
"one-click-instance.user-limit": 100,
"memcache.local": "\\OC\\Memcache\\APCu",
"apps_paths": [
{
"path": "\/var\/www\/html\/apps",
"url": "\/apps",
"writable": false
},
{
"path": "\/var\/www\/html\/custom_apps",
"url": "\/custom_apps",
"writable": true
}
],
"check_data_directory_permissions": false,
"memcache.distributed": "\\OC\\Memcache\\Redis",
"memcache.locking": "\\OC\\Memcache\\Redis",
"redis": {
"host": "***REMOVED SENSITIVE VALUE***",
"password": "***REMOVED SENSITIVE VALUE***",
"port": 6379,
"timeout": 3,
"read_timeout": 10
},
"overwritehost": "cloud.expatrealestate.de",
"overwriteprotocol": "https",
"passwordsalt": "***REMOVED SENSITIVE VALUE***",
"secret": "***REMOVED SENSITIVE VALUE***",
"trusted_domains": [
"localhost",
"cloud.expatrealestate.de"
],
"datadirectory": "***REMOVED SENSITIVE VALUE***",
"dbtype": "pgsql",
"version": "33.0.6.2",
"overwrite.cli.url": "https:\/\/cloud.expatrealestate.de\/",
"dbname": "***REMOVED SENSITIVE VALUE***",
"dbhost": "***REMOVED SENSITIVE VALUE***",
"dbtableprefix": "oc_",
"dbuser": "***REMOVED SENSITIVE VALUE***",
"dbpassword": "***REMOVED SENSITIVE VALUE***",
"installed": true,
"instanceid": "***REMOVED SENSITIVE VALUE***",
"maintenance": false,
"updatechecker": false,
"loglevel": 2,
"log_type": "file",
"logfile": "\/var\/www\/html\/data\/nextcloud.log",
"log_rotate_size": 10485760,
"log.condition": {
"apps": [
"admin_audit"
]
},
"preview_max_x": 2048,
"preview_max_y": 2048,
"jpeg_quality": 60,
"enabledPreviewProviders": {
"1": "OC\\Preview\\Image",
"2": "OC\\Preview\\MarkDown",
"3": "OC\\Preview\\MP3",
"4": "OC\\Preview\\TXT",
"5": "OC\\Preview\\OpenDocument",
"6": "OC\\Preview\\Movie",
"7": "OC\\Preview\\Krita",
"0": "OC\\Preview\\Imaginary",
"23": "OC\\Preview\\ImaginaryPDF"
},
"enable_previews": true,
"upgrade.disable-web": true,
"mail_smtpmode": "smtp",
"trashbin_retention_obligation": "auto, 30",
"versions_retention_obligation": "auto, 30",
"activity_expire_days": 30,
"simpleSignUpLink.shown": false,
"share_folder": "\/Shared",
"one-click-instance.link": "https:\/\/nextcloud.com\/all-in-one\/",
"upgrade.cli-upgrade-link": "https:\/\/github.com\/nextcloud\/all-in-one\/discussions\/2726",
"updatedirectory": "\/nc-updater",
"maintenance_window_start": 100,
"allow_local_remote_servers": true,
"davstorage.request_timeout": 3600,
"documentation_url.server_logs": "https:\/\/github.com\/nextcloud\/all-in-one\/discussions\/5425",
"htaccess.RewriteBase": "\/",
"dbpersistent": false,
"auth.bruteforce.protection.enabled": true,
"ratelimit.protection.enabled": true,
"files_external_allow_create_new_local": true,
"trusted_proxies": "***REMOVED SENSITIVE VALUE***",
"preview_imaginary_url": "***REMOVED SENSITIVE VALUE***",
"preview_imaginary_key": "***REMOVED SENSITIVE VALUE***",
"mail_smtphost": "***REMOVED SENSITIVE VALUE***",
"mail_smtpport": "587",
"mail_sendmailmode": "smtp",
"mail_from_address": "***REMOVED SENSITIVE VALUE***",
"mail_domain": "***REMOVED SENSITIVE VALUE***",
"mail_smtpauth": true,
"mail_smtpname": "***REMOVED SENSITIVE VALUE***",
"mail_smtppassword": "***REMOVED SENSITIVE VALUE***",
"serverid": 445,
"log_type_audit": "file",
"logfile_audit": "\/var\/www\/html\/data\/audit.log",
"onlyoffice": {
"editors_check_interval": 0,
"jwt_secret": "***REMOVED SENSITIVE VALUE***",
"jwt_header": "AuthorizationJwt"
},
"update_channel": "stable",
"DOMAIN": "cloud.expatrealestate.de",
"AIO_VERSION": "v13.4.0"
}
}
Browser
Browser name: Firefox
Browser version: 153
Operating system: Archlinux
Browser log
Uncaught TypeError: this.$set is not a function
fileStarted SendFilesModal.vue:409
sa filesplugin.js:266
8588 filesplugin.js:364
onSendClick SendFilesModal.vue:375
i runtime-core.esm-bundler.js:199
s runtime-core.esm-bundler.js:206
kt runtime-core.esm-bundler.js:4503
g NcButton-jvoYS2my.mjs:84
i runtime-core.esm-bundler.js:199
s runtime-core.esm-bundler.js:206
n runtime-dom.esm-bundler.js:768
SendFilesModal.vue:409:9
Network log: no request is issued at all when clicking send — the exception aborts the handler
before axios.post('apps/integration_mattermost/sendFile') is reached.
Confirmed in the installed bundle:
$ grep -o "this\.\$set([^)]*)" js/integration_mattermost-filesplugin.js
this.$set(this.fileStates,e,Un.IN_PROGRESS)
this.$set(this.fileStates,e,Un.FINISHED)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/components/SendFilesModal.vue at fileStarted() and fileFinished(), then trace the call from src/filesplugin.js around line 266. Replace the leftover Vue 2 state updates so file upload reaches axios.post and progress states still update; verify that sending a file posts it to Mattermost without the TypeError.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100