Taxonomy_autocomplete() is defined to have a callback at /taxonomy/autocomplete and gets a field name and the typed text as two arguments. However, if the field does not exist, the SQL generated will result in a massive SQL error due to no vid identified for the query:
An AJAX HTTP error occurred.
HTTP Result Code: 500
Debugging information follows.
Path: http://............./taxonomy/autocomplete/field_tags
StatusText: OK
ResponseText: PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')) AND (t.name LIKE '%terzg%' ESCAPE '\\')
LIMIT 10 OFFSET 0' at line 1: SELECT t.tid AS tid, t.name AS name
FROM
{taxonomy_term_data} t
WHERE (t.name NOT IN (:db_condition_placeholder_0, :db_condition_placeholder_1)) AND (t.vid IN ()) AND (t.name LIKE :db_condition_placeholder_2 ESCAPE '\\')
LIMIT 10 OFFSET 0; Array
(
[:db_condition_placeholder_0] => mat
[:db_condition_placeholder_1] => test
[:db_condition_placeholder_2] => %terzg%
)
in taxonomy_autocomplete() (line 106 of /............../docroot/modules/taxonomy/taxonomy.pages.inc).
We need to somehow validate that the field exists (can be loaded). Probably better to validate that we actually have a taxonomy field at play here and that it has associated vids (which the settings screen tries to ensure though). So the attached patch is a rough start to show how to avert the issue.
Comments
Comment #1
JacobSingh commentedI don't like this... I think it obfuscates the problem. At least now the user has a chance of debugging what is wrong. I know core doesn't really have an AJAX error handling framework, and can't handle an error gracefully in the autocomplete code. But for now, at least logging something would be good if we can't throw a big ol' alert.
-J
Comment #2
gábor hojtsyWell, people and all kinds of bots visit random URLs. They'll get this error unless we stop before the SQL queries are executed. What kind of logging are you looking for? Throw in a watchdog log before returning an array?
Comment #3
JacobSingh commentedI don't understand the "random URL" argument... Why would a bot visit a URL which wasn't linked to anywhere? And if it did, why would we care if it got an ugly error? I must be missing the point :)
Logging to watchdog is not a bad step, although how hard would it be to return a more digestible error which showed up in an alert() like "The field $field does not exist, please check the configuration of this free tagging box" or something like that...
Comment #4
gábor hojtsyThe bot would fill up the watchdog log with SQL errors like the above. Generally I don't agree it is a good idea to run SQL queries we know will break and throw errors. If we know an SQL query will break, why attempt to execute it?
Autocomplete callbacks are current required to return rendered JSON data. How you imagine putting an alert() in the JSON data structure? Short of rearchitecting how misc/autocomplete.js works, looks like the only thing we could do is to leverage the error handling in in misc/autocomplete.js where Drupal.ACDB.prototype.search() handles the URI return value error. That already throws an alert on error.
In general I don't think we should bother the user that they tried to get autocomplete for a nonexistent field, since the error is actually in the code displaying the field. I see how displaying this error could be useful for debugging, not for the user.
Comment #5
JacobSingh commentedI totally agree, that's why I'm very pro-exception handling. Even if they do break, we shouldn't be passing that info directly back to users or developers really.
However, if we commit this patch, what is the difference between "didn't find any matching tags" and "your form field is totally broken and referencing a non-existant column in the database". It becomes almost impossible to debug.
I still don't understand how a bot would be trying to autocomplete a bad autocomplete field repetitively... OR are you saying that the watchdog will log when the field just shows? If that's the case, I still think some kind of logging / error handling is required. If a bot slams it, great, the developer will find the bug sooner.
In terms of re-architecting autocomplete.js, etc I agree and mentioned that we can't fix that right now in my first reply. What happens if you return a string instead of JSON though? It sounds to me like it is "handling" the SQL error by just dumping in an alert. What if we returned our digestible error in a string, would it end up in an alert as well?
Comment #6
gábor hojtsyYes, we can return a string and get it displayed as a short and hardly noticeable part of a long message. Is this better?
Comment #7
JacobSingh commentedI think so. Does it work for you still?
Comment #8
yched commentedWhile you're there, you could check that the field is indeed a taxonomy field
and also that field_access('view') is true - since you're about to disclose information about the values in this field.
Comment #9
ksenzeeLike this?
Comment #10
yched commentedre @ksenzee #9 : yup. As a nitpick, I'm not sure the various 'not OK' cases are worth generating specific error messages - the 403 for the specific case of !field_access('view', $field) is needed, other cases could just result in "Taxonomy field @field_name not found.", this is just safeguard for a case that's not supposed to happen anyway.
I'm not able to apply or test patches right now, so I'll leave others RTBC.
Comment #11
ksenzeeTrue. I was thinking I should check field access before checking field type, but it doesn't really matter, and it's less work for translators this way. New patch attached.
Comment #12
David_Rothstein commentedThe latest patch here adds a translatable string, so I'm giving this issue the "string freeze" tag. We could probably do it without adding a new string if we absolutely had to though.
Comment #13
gábor hojtsyLooks good now.
Comment #14
webchickTests, please.
Comment #15
David_Rothstein commentedThe field_access() call in this patch also has the wrong syntax (it is missing the required third parameter).
Comment #16
David_Rothstein commentedPerhaps also it should get a code comment or something. It is not easy to understand why we want to check field access here, and it misled me for a bit (I thought maybe it was a security issue that we don't have this, but it turns out it isn't, since taxonomy terms in general are already possible for anyone with 'access content' permission to find out).
Comment #17
David_Rothstein commentedOn further thought, I'm not sure the field_access() call belongs here at all. It seems like all it does is make the taxonomy autocomplete callback less generically useful. (I am writing some code for Views that uses this autocomplete callback, and adding the field access check as done in this patch would cause a bit of pain for that use case.)
The function takes a field as input, but only returns a list of terms as output; it does not return any content from the field itself. So I think the only access check that matters here is term_access (which the function already does).
Comment #18
yched commentedI'd tend to agree. We're not displaying actual values of the field (for which you'd need 'view field' access), but a list of terms in a vocab. This has nothing to do with field_access().
Comment #19
JacobSingh commented#11: 814804-11-taxonomy-autocomplete-error.patch queued for re-testing.
Comment #21
JacobSingh commentedHere is one w/oo the field_access
Comment #22
David_Rothstein commentedWhy is there a new parameter? That looks like a mistake.
Comment #24
JacobSingh commentedoops, absolutely right. Let me fix that.
Comment #25
JacobSingh commentedshouldn't make patches before coffee. How's this one?
Comment #27
JacobSingh commentedokay, for reals this time.
Comment #28
David_Rothstein commentedThat looks good to me. Still needs a test per #14.
Comment #29
draenen commentedAdded test to #27 per #14
Comment #30
draenen commentedTrying again.
Comment #31
steven jones commentedSubscribe.
Comment #32
ksenzeeTest looks good. Made some spelling and other minor fixes. Also moving to 8.x - it's a backport candidate though.
Comment #33
jlaurin commentedSomeone else gets this error when trying to patch? :
patch -p1 < taxonomy-error.patch
patching file modules/taxonomy/taxonomy.pages.inc
Hunk #1 succeeded at 74 (offset -2 lines).
patching file modules/taxonomy/taxonomy.test
Hunk #1 FAILED at 597.
1 out of 1 hunk FAILED -- saving rejects to file modules/taxonomy/taxonomy.test.rej
Thank you
Comment #34
paul.lovvik commentedRerolled the patch.
Comment #36
paul.lovvik commentedOdd, the patch applied for me. I have rolled it again, testing on both D8 and D7.
Comment #37
David_Rothstein commentedComment #38
xjmRerolled for core/.
Comment #39
c960657 commentedRequires a reroll after #93854: Allow autocompletion requests to include slashes has been fixed.
Comment #40
David_Rothstein commentedIt looks like #93854: Allow autocompletion requests to include slashes was rolled back, but the patch here needs a reroll for other reasons anyway.
Here are up-to-date versions for both D7 and D8.
Comment #41
David_Rothstein commentedSorry for the issue queue noise, but for Drush Make purposes I need a patch against Drupal 7.10, and the above one doesn't apply there.... So in case anyone else needs to run this patch against Drupal 7.10, here it is :)
Comment #42
xjmThis is ready to go once again. :)
Comment #43
catch#40: autocomplete_query_error-814804-40.patch queued for re-testing.
Comment #45
xjmJust a reroll to accomodate another addition to the autocomplete tests.
Comment #46
tamasd commentedReroll of David's patch in #41 for Drupal 7.12.
Comment #47
catchThanks for the re-roll. Committed/pushed to 8.x, moving back to 7.x.
Comment #48
xjmRenamed for the bot.
Comment #50
ksenzeeThis is back to RTBC.
Comment #51
webchickCommitted and pushed to 7.x. Thanks!
Comment #54
g33kg1rl commentedI received this error on my 7.x website. The 7.x patch doesn't apply to the latest core. Any suggestions?
Comment #55
g33kg1rl commentedDifferent cause, same error message.